@expofp/floorplan 3.25.2 → 3.27.0

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 (226) hide show
  1. package/dist/browser/{Button-DZ5RJVoX.js → Button-e8P-AcfW.js} +6 -6
  2. package/dist/browser/{CookieConsent-CNE-7zNI.js → CookieConsent-DT6PZdD-.js} +8 -8
  3. package/dist/browser/{Debug-TDQ_xzea.js → Debug-Btnxv9GC.js} +8 -8
  4. package/dist/browser/DebugTools-CH_HoQal.js +1922 -0
  5. package/dist/browser/{Demo-A0X5mRqG.js → Demo-DZoFFss-.js} +10 -10
  6. package/dist/browser/{Free-BjYK0xDM.js → Free-DiFQkGSU.js} +10 -10
  7. package/dist/browser/{GalleryContainer-BsQuHOrj.js → GalleryContainer-aJ6EZ5I3.js} +11 -11
  8. package/dist/browser/{GpsLoader-DoutzmU_.js → GpsLoader-Bu9mBOam.js} +34 -34
  9. package/dist/browser/KioskStore-DUC4jNn0.js +241 -0
  10. package/dist/browser/{MaplibreAdapter-W1ZdQQ00.js → MaplibreAdapter-DIlDXt73.js} +2067 -2152
  11. package/dist/browser/{ModalContainer-BfZm0B_L.js → ModalContainer-CVRxdpt2.js} +11 -11
  12. package/dist/browser/{PermissionNotice-Cm6qrOC_.js → PermissionNotice-B5X5RQja.js} +7 -7
  13. package/dist/browser/SetKioskMode-BbDnU98F.js +48 -0
  14. package/dist/browser/{ShowKiosk-B0cj0p6h.js → ShowKiosk-B7HfONvN.js} +11 -11
  15. package/dist/browser/{ViewerMenuPanel-FFmV-n9m.js → ViewerMenuPanel-CT6kvVUw.js} +17 -17
  16. package/dist/browser/{add-debug-secret-listener-BOW3NQe7.js → add-debug-secret-listener-Dvv-Pg0-.js} +1 -1
  17. package/dist/browser/{adopt-global-settings-DNTNdr3z.js → adopt-global-settings-CXzCKJtp.js} +10 -10
  18. package/dist/browser/{boolean-editor-Bx4HLLyu.js → boolean-editor-CHMR9ZwP.js} +10 -10
  19. package/dist/browser/{bootIntercom-C_8HLvxg.js → bootIntercom-DQcGuly8.js} +3 -3
  20. package/dist/browser/bundle.json +77 -65
  21. package/dist/browser/camera-events-BkrzcISl.js +18 -0
  22. package/dist/browser/{classnames-DovQg6we.js → classnames-BYuGpzao.js} +2 -2
  23. package/dist/browser/{client-CadlVOps.js → client-hxMr1frV.js} +793 -992
  24. package/dist/browser/{components-BK-czcTL.js → components-DiB2l4Q7.js} +1934 -1986
  25. package/dist/browser/debug-context-CfyAAxAt.js +24315 -0
  26. package/dist/browser/{debug-overlay-vFTynZrP.js → debug-overlay-PYUvPcx-.js} +11 -11
  27. package/dist/browser/{debug-ui-BgSppEQg.js → debug-ui-BXRAYxv6.js} +7 -7
  28. package/dist/browser/dimming-Dj-1kBgQ.js +1108 -0
  29. package/dist/browser/{dist-C1WQpGAq.js → dist-30RVEJTr.js} +7 -7
  30. package/dist/browser/{dist-CkAU9dsV.js → dist-DgGMS59X.js} +6 -6
  31. package/dist/browser/{dist-gIYlJ33F.js → dist-opCvrhNh.js} +3 -3
  32. package/dist/browser/{efp-debug-init-CGEJSmuk.js → efp-debug-init-CYfrcz9M.js} +4 -4
  33. package/dist/browser/{enum-editor-BZXgS3I-.js → enum-editor-BYO96W3-.js} +5 -5
  34. package/dist/browser/{es5-DoqUhz95.js → es5-Bpzk_wCi.js} +2 -2
  35. package/dist/browser/{event-not-found-Dl66nXH1.js → event-not-found-DEepFxEc.js} +1 -1
  36. package/dist/browser/{exports-CK5UTqgq.js → exports-Bo5VUoiX.js} +1 -1
  37. package/dist/browser/{favicon-BnTLQysW.js → favicon-Bf88cI9_.js} +1 -1
  38. package/dist/browser/{fetch-retry.umd-D_tGjwEb.js → fetch-retry.umd-D2BnNN8g.js} +2 -2
  39. package/dist/browser/{flex-BCrAgMxK.js → flex-B5cqWC1b.js} +6 -6
  40. package/dist/browser/{floorplan.loader-DXJR9eeS.js → floorplan.loader-D3lRYRJS.js} +10 -10
  41. package/dist/browser/{floorplan.ready-C0sdmceF.js → floorplan.ready-CsdDpbEv.js} +343 -307
  42. package/dist/browser/{fuse-C7evxCwi.js → fuse-CzalO4Mu.js} +2 -2
  43. package/dist/browser/{i18n-Cp32ZzDq.js → i18n-D1sb3MoT.js} +5 -5
  44. package/dist/browser/index.js +14 -14
  45. package/dist/browser/{index.module-CeDH7KeK.js → index.module-JxYvexTC.js} +4 -4
  46. package/dist/browser/{integrateKiosk-JZG1AZBF.js → integrateKiosk-e4HqZu2W.js} +5 -5
  47. package/dist/browser/{is-webview-Be9due3O.js → is-webview-ChPDTaTY.js} +1 -1
  48. package/dist/browser/{jsx-runtime-DwNSQYOA.js → jsx-runtime-Ca1Wj_4-.js} +2 -2
  49. package/dist/browser/{kiosk-record-BMwfA16j.js → kiosk-record-C2cafcoW.js} +1 -1
  50. package/dist/browser/{lib-DeQ47J_S.js → lib-DXqE6M9Z.js} +3 -3
  51. package/dist/browser/{loadImage-DVBOry5-.js → loadImage-8qYzT9NG.js} +4 -4
  52. package/dist/browser/{logDeviceInfo-uPn7yfGH.js → logDeviceInfo-CF95RwQH.js} +9 -9
  53. package/dist/browser/{mobx-DFFcUY2e.js → mobx-B8aGIDdz.js} +7 -7
  54. package/dist/browser/{optional-boolean-editor-DfcaW7-l.js → optional-boolean-editor-D02Q8KUS.js} +4 -4
  55. package/dist/browser/{optional-enum-editor-SEARu4hs.js → optional-enum-editor-RV_EKfNQ.js} +5 -5
  56. package/dist/browser/{optional-string-editor-COLkp8EA.js → optional-string-editor-D_t_aZG2.js} +5 -5
  57. package/dist/browser/{particles.min-DHvuM5ou.js → particles.min-CDyH_67D.js} +2 -2
  58. package/dist/browser/{react-BNCBBLDK.js → react-CDmIhEY6.js} +2 -2
  59. package/dist/browser/{react-dom-ql8ZgjdB.js → react-dom-PGvJwDoR.js} +3 -3
  60. package/dist/browser/{rolldown-runtime-D0mAPq9J.js → rolldown-runtime-CwqkRsWu.js} +1 -1
  61. package/dist/browser/scheduler-MBFOnOYr.js +212 -0
  62. package/dist/browser/{select-CwB0Zi7C.js → select-2x53pvd0.js} +11 -11
  63. package/dist/browser/{settings-MzAuoQZ6.js → settings-BCkl8gdb.js} +2 -2
  64. package/dist/browser/{settings-item-Ca6s5CDf.js → settings-item-DT6Vnw06.js} +7 -7
  65. package/dist/browser/store-Dej5FGrq.js +31205 -0
  66. package/dist/browser/{string-editor-BjOeNcgJ.js → string-editor-w9YDgRoR.js} +5 -5
  67. package/dist/browser/{text-field-6Ccfbuuo.js → text-field-ricOc0h0.js} +6 -6
  68. package/dist/browser/{theme-XlV0fBPc.js → theme-Ce7vpk9b.js} +9 -9
  69. package/dist/browser/{ui-BopruaHZ.js → ui-PDV2rEkU.js} +9 -9
  70. package/dist/browser/{useRenderTarget-CdH-VI6E.js → useRenderTarget-DroCs5kL.js} +5 -5
  71. package/dist/browser/viewport-Jwms2MJD.js +41 -0
  72. package/dist/esm/components/Booth/Booth.js +1 -1
  73. package/dist/esm/components/Event.js +1 -1
  74. package/dist/esm/components/Exhibitor.js +1 -1
  75. package/dist/esm/components/Kiosk/KioskStore.d.ts +5 -2
  76. package/dist/esm/components/Kiosk/KioskStore.js +1 -1
  77. package/dist/esm/components/Kiosk/SetKioskMode.d.ts +1 -2
  78. package/dist/esm/components/Kiosk/SetKioskMode.js +1 -1
  79. package/dist/esm/components/Layout.js +1 -1
  80. package/dist/esm/components/Map/Map.d.ts +1 -1
  81. package/dist/esm/components/Map/Map.js +1 -1
  82. package/dist/esm/components/Map/MapCamera.d.ts +17 -0
  83. package/dist/esm/components/Map/MapCamera.js +1 -0
  84. package/dist/esm/components/Map/MapViewport.d.ts +12 -0
  85. package/dist/esm/components/Map/MapViewport.js +1 -0
  86. package/dist/esm/components/Map/booth-by-xy.d.ts +13 -0
  87. package/dist/esm/components/Map/booth-by-xy.js +1 -1
  88. package/dist/esm/components/Map/camera-events.d.ts +16 -0
  89. package/dist/esm/components/Map/camera-events.js +1 -0
  90. package/dist/esm/components/Map/camera.d.ts +48 -0
  91. package/dist/esm/components/Map/camera.js +1 -0
  92. package/dist/esm/components/Map/drawing/config/TextFitter.d.ts +1 -1
  93. package/dist/esm/components/Map/drawing/config/config-all.d.ts +1 -2
  94. package/dist/esm/components/Map/drawing/config/config-all.js +1 -1
  95. package/dist/esm/components/Map/drawing/config/config-bg.d.ts +1 -2
  96. package/dist/esm/components/Map/drawing/config/config-bg.js +1 -1
  97. package/dist/esm/components/Map/drawing/config/config-booth-badge.d.ts +70 -3
  98. package/dist/esm/components/Map/drawing/config/config-booth-badge.js +1 -1
  99. package/dist/esm/components/Map/drawing/config/config-booth-bg.d.ts +3 -6
  100. package/dist/esm/components/Map/drawing/config/config-booth-bg.js +1 -1
  101. package/dist/esm/components/Map/drawing/config/config-booth-bookmark.d.ts +11 -7
  102. package/dist/esm/components/Map/drawing/config/config-booth-bookmark.js +1 -1
  103. package/dist/esm/components/Map/drawing/config/config-booth-border.d.ts +2 -3
  104. package/dist/esm/components/Map/drawing/config/config-booth-border.js +1 -1
  105. package/dist/esm/components/Map/drawing/config/config-booth-labels-special.d.ts +16 -3
  106. package/dist/esm/components/Map/drawing/config/config-booth-labels-special.js +2 -2
  107. package/dist/esm/components/Map/drawing/config/config-booth-labels.d.ts +18 -4
  108. package/dist/esm/components/Map/drawing/config/config-booth-labels.js +1 -1
  109. package/dist/esm/components/Map/drawing/config/config-booths.d.ts +1 -2
  110. package/dist/esm/components/Map/drawing/config/config-booths.js +1 -1
  111. package/dist/esm/components/Map/drawing/config/config-load-layer.d.ts +1 -2
  112. package/dist/esm/components/Map/drawing/config/config-load-layer.js +1 -1
  113. package/dist/esm/components/Map/drawing/config/config-markers.d.ts +23 -2
  114. package/dist/esm/components/Map/drawing/config/config-markers.js +1 -1
  115. package/dist/esm/components/Map/drawing/config/layer-images.d.ts +35 -0
  116. package/dist/esm/components/Map/drawing/config/layer-images.js +1 -0
  117. package/dist/esm/components/Map/drawing/config/loadBoothsImages.d.ts +38 -3
  118. package/dist/esm/components/Map/drawing/config/loadBoothsImages.js +1 -1
  119. package/dist/esm/components/Map/pointer.d.ts +73 -0
  120. package/dist/esm/components/Map/pointer.js +1 -0
  121. package/dist/esm/components/Map/scene.d.ts +20 -0
  122. package/dist/esm/components/Map/scene.js +1 -0
  123. package/dist/esm/components/Map/traffic/trafficLayers.d.ts +2 -7
  124. package/dist/esm/components/Map/traffic/trafficLayers.js +1 -1
  125. package/dist/esm/components/Map/traffic/useBuildRoute.d.ts +4 -3
  126. package/dist/esm/components/Map/traffic/useBuildRoute.js +6 -6
  127. package/dist/esm/components/Map/traffic/useManageTraffic.d.ts +4 -3
  128. package/dist/esm/components/Map/traffic/useManageTraffic.js +1 -1
  129. package/dist/esm/components/Map/viewport.d.ts +63 -0
  130. package/dist/esm/components/Map/viewport.js +1 -0
  131. package/dist/esm/components/Maplibre/MaplibreAdapter.d.ts +6 -2
  132. package/dist/esm/components/Maplibre/MaplibreAdapter.js +1 -1
  133. package/dist/esm/components/Maplibre/MaplibreWrapper.d.ts +30 -8
  134. package/dist/esm/components/Maplibre/MaplibreWrapper.js +1 -1
  135. package/dist/esm/components/Maplibre/useDimming.d.ts +2 -2
  136. package/dist/esm/components/Maplibre/useDimming.js +1 -1
  137. package/dist/esm/components/Maplibre/useKioskIdleEvents.d.ts +5 -6
  138. package/dist/esm/components/Maplibre/useLayerVisibilitySync.d.ts +2 -2
  139. package/dist/esm/components/Maplibre/useLayerVisibilitySync.js +1 -1
  140. package/dist/esm/components/Maplibre/usePoiMarkers.d.ts +1 -2
  141. package/dist/esm/components/Maplibre/useWayfindingAndMarkers.d.ts +8 -5
  142. package/dist/esm/components/Maplibre/useWayfindingAndMarkers.js +1 -1
  143. package/dist/esm/components/Maplibre/utils/layer-defs.d.ts +8 -3
  144. package/dist/esm/components/Maplibre/utils/layer-defs.js +1 -1
  145. package/dist/esm/components/Maplibre/utils/poi-marker-hit-test.d.ts +3 -3
  146. package/dist/esm/components/Speaker.js +1 -1
  147. package/dist/esm/components/Ws.js +1 -1
  148. package/dist/esm/engine/defs.d.ts +30 -0
  149. package/dist/esm/engine/defs.js +3 -0
  150. package/dist/esm/engine/fonts.js +1 -0
  151. package/dist/esm/engine/update-def.d.ts +52 -0
  152. package/dist/esm/engine/update-def.js +1 -0
  153. package/dist/esm/engine/utils/rotation.d.ts +6 -0
  154. package/dist/esm/engine/utils/rotation.js +1 -0
  155. package/dist/esm/floorplan.ready.d.ts +2 -0
  156. package/dist/esm/floorplan.ready.js +1 -1
  157. package/dist/esm/services/url-sync.js +1 -1
  158. package/dist/esm/store/BoothStore.d.ts +11 -0
  159. package/dist/esm/store/HeatmapStore.d.ts +9 -0
  160. package/dist/esm/store/LayerStore.d.ts +2 -0
  161. package/dist/esm/store/LayerStore.js +1 -1
  162. package/dist/esm/store/RootStore.d.ts +0 -2
  163. package/dist/esm/store/RootStore.js +1 -1
  164. package/dist/esm/store/RouteStore.js +1 -1
  165. package/dist/esm/store/ShortcutRegistry.d.ts +14 -0
  166. package/dist/esm/store/ShortcutRegistry.js +1 -1
  167. package/dist/esm/store/UIState.js +1 -1
  168. package/dist/esm/store/details-events.d.ts +11 -0
  169. package/dist/esm/store/details-events.js +1 -0
  170. package/dist/esm/store/init/init-booths.js +1 -1
  171. package/dist/esm/store/providers/SessionsSubButtonProvider.d.ts +18 -0
  172. package/dist/esm/store/providers/SessionsSubButtonProvider.js +1 -1
  173. package/dist/esm/store/search-buttons/SearchButtonsActions.d.ts +15 -2
  174. package/dist/esm/store/search-buttons/SearchButtonsActions.js +1 -1
  175. package/dist/esm/store/search-buttons/SearchButtonsFactory.js +1 -1
  176. package/dist/esm/store/search-buttons/SearchButtonsStore.d.ts +3 -3
  177. package/dist/esm/store/search-buttons/SearchButtonsStore.js +1 -1
  178. package/dist/esm/tools/gtag.d.ts +1 -0
  179. package/dist/esm/tools/gtag.js +1 -1
  180. package/dist/esm/tools/telemetry.d.ts +2 -0
  181. package/dist/esm/tools/telemetry.js +1 -1
  182. package/dist/esm/tools/track-event.d.ts +26 -2
  183. package/dist/esm/tools/track-event.js +1 -1
  184. package/dist/esm/utils/dimming.d.ts +13 -2
  185. package/dist/esm/utils/dimming.js +1 -1
  186. package/dist/esm/utils/mobx.d.ts +2 -2
  187. package/dist/esm/utils/mobx.js +1 -1
  188. package/dist/esm/utils/scene-bounds.d.ts +1 -1
  189. package/dist/esm/utils/scene-bounds.js +1 -1
  190. package/dist/esm/wayfinding/adapters/canvasIconProvider.js +1 -1
  191. package/dist/esm/wayfinding/createWayfinding.d.ts +19 -2
  192. package/dist/esm/wayfinding/createWayfinding.js +1 -1
  193. package/package.json +11 -10
  194. package/dist/browser/KioskStore-CRN9B487.js +0 -290
  195. package/dist/browser/SetKioskMode-BlmUmBkH.js +0 -57
  196. package/dist/browser/booth-by-xy-DgXTlV8u.js +0 -1130
  197. package/dist/browser/main-WTEdqNkt.js +0 -289
  198. package/dist/browser/store-B_c3r86U.js +0 -41370
  199. package/dist/esm/components/Map/pointInConvexQuad.d.ts +0 -3
  200. package/dist/esm/components/Map/pointInConvexQuad.js +0 -1
  201. package/dist/esm/components/Map/visibleArea.d.ts +0 -16
  202. package/dist/esm/components/Map/visibleArea.js +0 -1
  203. package/dist/esm/components/Maplibre/useRendererEvents.d.ts +0 -9
  204. package/dist/esm/components/Maplibre/useRendererEvents.js +0 -1
  205. package/dist/esm/components/Maplibre/utils/update-pump.d.ts +0 -18
  206. package/dist/esm/components/Maplibre/utils/update-pump.js +0 -1
  207. package/dist/esm/renderer/HandlerRegistry.d.ts +0 -18
  208. package/dist/esm/renderer/HandlerRegistry.js +0 -1
  209. package/dist/esm/renderer/RendererService.d.ts +0 -44
  210. package/dist/esm/renderer/RendererService.js +0 -1
  211. package/dist/esm/renderer/engine-core/defs.d.ts +0 -40
  212. package/dist/esm/renderer/engine-core/defs.js +0 -3
  213. package/dist/esm/renderer/engine-core/fonts.js +0 -1
  214. package/dist/esm/renderer/engine-core/settings.d.ts +0 -4
  215. package/dist/esm/renderer/engine-core/settings.js +0 -1
  216. package/dist/esm/renderer/engine-core/types.d.ts +0 -50
  217. package/dist/esm/renderer/engine-core/types.js +0 -1
  218. package/dist/esm/renderer/engine-core/update-def.d.ts +0 -12
  219. package/dist/esm/renderer/engine-core/update-def.js +0 -1
  220. package/dist/esm/renderer/engine-core/utils/rotation.d.ts +0 -17
  221. package/dist/esm/renderer/engine-core/utils/rotation.js +0 -1
  222. package/dist/esm/renderer/index.d.ts +0 -19
  223. package/dist/esm/renderer/index.js +0 -1
  224. /package/dist/esm/{renderer/engine-core → engine}/canvases.d.ts +0 -0
  225. /package/dist/esm/{renderer/engine-core → engine}/canvases.js +0 -0
  226. /package/dist/esm/{renderer/engine-core → engine}/fonts.d.ts +0 -0
@@ -1 +1 @@
1
- import{getConfig as x}from"@expofp/config";import{degToRad as T,Rect as D}from"@expofp/geometry";import{resolve as H}from"@expofp/resolve";import{BOOTHS_PAINTER_MARKER as k,SEPARATOR as m}from"../../../../constants";import{getFpPaths as v}from"../../../../data/fp-payloads";import{createImageDef as F,createLayerDef as R}from"../../../../renderer";import c,{boothStore as G}from"../../../../store";import K from"../../../../store/init/init-booths";import{getChildLayers as Y}from"../../../../store/init/init-layers";import{LayersMode as j}from"../../../../store/LayerStore";import{chunkArray as J}from"../../../../utils";import{loadIcons as U}from"../../../../utils/imageloader";import Z,{BG_LAYER_NAME as $,FG_LAYER_NAME as E}from"./config-bg";import q,{BOOTHS_CHUNK_SIZE as z}from"./config-booths";import{configOutdoorPoiLayer as Q}from"./config-outdoor-poi";import{getImageLayerName as V,getLayerIcons as W}from"./loadBoothsImages";function X(e){return e.childLayers.length?e.childLayers:Y(e,e.basePriority,15).layers}function I(e,r,f){return new Promise(async h=>{let n=[];const i=K(c,r);if(Q(r,i)){r.loaded=!0,r.configured=!0,r.children=[],h(R(r.name,[],{hidden:!0}));return}const s=await Z(r),a=[],d=J(i,z),l=G.booths.filter(o=>o.rect&&(!o.layer||o.layer===r||o.layer.childLayers.includes(r))&&o.exhibitors.find(t=>!!t.logoInBooth&&!!t.logo?.url)&&!c.uiState.hideLogoInBooth),B=new Map(l.map(o=>[o.id,o.noLabels]));l.forEach(o=>o.noLabels=!0),i.length&&d.forEach((o,t)=>{a.push(q(e,`${r.name}${m}${k}${m}${t}`,o))}),l.forEach(o=>{o.noLabels=B.get(o.id)}),r.loaded=!0;const u=s.children.find(o=>o.name===$),y=s.children.find(o=>o.name===E),p=V(r.name),g=W(r),L={name:p,children:[]};g.length&&e.onLayerImages(p,async()=>{const o=await U(g),t=[];for(const A of o.filter(Boolean)){const{bounds:{x:P,y:b,height:S,angle:_,width:M},htmlImage:N}=A,C=D.fromMinMax({x:P,y:b},{x:P+M,y:b+S},T(_)),O=F(N,C);t.push({shape:O})}return{layer:L,children:t}}),u&&n.push({...u,name:`${s.name}${m}${$}`}),a.length&&n.push(...a),y&&n.push({...y,name:`${s.name}${m}${E}`}),g.length&&n.push(L);const w=r.childLayers.sort((o,t)=>o.basePriority-t.basePriority).map(async o=>I(e,o,!0));Promise.all(w).then(o=>{const t=o.flat();t.length&&n.push(...t),r.children=n,r.configured=!0,h(R(r.name,n,{hidden:!f}))})})}export default async function oo(e,r){return e.configured?Promise.resolve({name:e.name,children:e.children}):new Promise(async(f,h)=>{if(c.layerStore.mode!==j.Default&&!v(e.name)&&!e.rootParent)try{const a=x().fpSvgLayerJsRefs[e.name];a&&await H(a)}catch(a){console.warn(`Layer data not loaded: ${e.name}`,a)}const n=X(e);n.length&&(e.childLayers=n);const{layers:i}=c.layerStore;c.layerStore.layers=[...i,...n.filter(a=>!i.some(d=>d.name===a.name))];const s=await I(r,e,e.visible);f(s)})}
1
+ import{getConfig as T}from"@expofp/config";import{degToRad as v,Rect as D}from"@expofp/geometry";import{resolve as F}from"@expofp/resolve";import{BOOTHS_PAINTER_MARKER as G,SEPARATOR as m}from"../../../../constants";import{getFpPaths as H}from"../../../../data/fp-payloads";import{createImageDef as k,createLayerDef as g}from"../../../../engine/defs";import s,{boothStore as K}from"../../../../store";import Y from"../../../../store/init/init-booths";import{getChildLayers as j}from"../../../../store/init/init-layers";import{LayersMode as J}from"../../../../store/LayerStore";import{chunkArray as U}from"../../../../utils";import{loadIcons as Z}from"../../../../utils/imageloader";import q,{BG_LAYER_NAME as R,FG_LAYER_NAME as $}from"./config-bg";import z,{BOOTHS_CHUNK_SIZE as Q}from"./config-booths";import{configOutdoorPoiLayer as V}from"./config-outdoor-poi";import{registerLayerImages as W}from"./layer-images";import{createModelDefFromElement as X,getImageLayerName as ee,getLayerGraphics as oe,getModelLayerName as re}from"./loadBoothsImages";function te(e){return e.childLayers.length?e.childLayers:j(e,e.basePriority,15).layers}function S(e,c){return new Promise(async f=>{let r=[];const a=Y(s,e);if(V(e,a)){e.loaded=!0,e.configured=!0,e.children=[],f(g(e.name,[],{hidden:!0}));return}const i=await q(e),n=[],h=U(a,Q),d=K.booths.filter(o=>o.rect&&(!o.layer||o.layer===e||o.layer.childLayers.includes(e))&&o.exhibitors.find(t=>!!t.logoInBooth&&!!t.logo?.url)&&!s.uiState.hideLogoInBooth),B=new Map(d.map(o=>[o.id,o.noLabels]));d.forEach(o=>o.noLabels=!0),a.length&&h.forEach((o,t)=>{n.push(z(`${e.name}${m}${G}${m}${t}`,o))}),d.forEach(o=>{o.noLabels=B.get(o.id)}),e.loaded=!0;const u=i.children.find(o=>o.name===R),y=i.children.find(o=>o.name===$),p=ee(e.name),{icons:l,models:I}=oe(e),L={name:p,children:[]},b={name:re(e.name),children:I.map(X)};l.length&&W(p,async()=>{const o=await Z(l),t=[];for(const A of o.filter(Boolean)){const{bounds:{x:E,y:P,height:M,angle:N,width:_},htmlImage:C}=A,O=D.fromMinMax({x:E,y:P},{x:E+_,y:P+M},v(N)),x=k(C,O);t.push({shape:x})}return{layer:L,children:t}}),u&&r.push({...u,name:`${i.name}${m}${R}`}),n.length&&r.push(...n),y&&r.push({...y,name:`${i.name}${m}${$}`}),l.length&&r.push(L),b.children.length&&r.push(b);const w=e.childLayers.sort((o,t)=>o.basePriority-t.basePriority).map(async o=>S(o,!0));Promise.all(w).then(o=>{const t=o.flat();t.length&&r.push(...t),e.children=r,e.configured=!0,f(g(e.name,r,{hidden:!c}))})})}export default async function ne(e){return e.configured?g(e.name,e.children,{hidden:!e.visible}):new Promise(async(c,f)=>{if(s.layerStore.mode!==J.Default&&!H(e.name)&&!e.rootParent)try{const n=T().fpSvgLayerJsRefs[e.name];n&&await F(n)}catch(n){console.warn(`Layer data not loaded: ${e.name}`,n)}const r=te(e);r.length&&(e.childLayers=r);const{layers:a}=s.layerStore;s.layerStore.layers=[...a,...r.filter(n=>!a.some(h=>h.name===n.name))];const i=await S(e,e.visible);c(i)})}
@@ -1,5 +1,26 @@
1
- import { RendererService } from '../../../../renderer';
1
+ import { SceneDef } from '@expofp/renderer';
2
+ import { FloorPlanMarkerEvent } from '../../../../types';
2
3
  export declare const MARKER_LAYER_NAME = "markers";
3
- export declare function configMarkers(rendererService: RendererService): () => void;
4
+ /** What {@link configMarkers} needs: the scene whose root layers hold the marker layer. */
5
+ export interface MarkerOptions {
6
+ /** The scene markers are drawn into; `config-all` pre-creates their layer in it. */
7
+ readonly scene: SceneDef;
8
+ }
9
+ /**
10
+ * Draws the plan's markers into a renderer scene and keeps them current with the store.
11
+ * @param options - The scene to draw into.
12
+ * @returns A disposer.
13
+ */
14
+ export declare function configMarkers(options: MarkerOptions): () => void;
15
+ /**
16
+ * The marker a click on the plan landed on, at the size markers are currently drawn.
17
+ *
18
+ * The pixel size comes from the marker layer's own handler rather than from a renderer the plan holds
19
+ * a reference to — which is the whole of what this adds over {@link getMarkerFromClick}.
20
+ * @param x - Where the click landed, in plan units.
21
+ * @param y - Where the click landed, in plan units.
22
+ * @returns The marker, or `null` when the click reached none.
23
+ */
24
+ export declare function markerAt(x: number, y: number): FloorPlanMarkerEvent | null;
4
25
  export declare function getMarkerFromClick(x: number, y: number, scale: number): import("../../../../store/RouteStore").Marker | null;
5
26
  //# sourceMappingURL=config-markers.d.ts.map
@@ -1 +1 @@
1
- import{Box as K,degToRad as T}from"@expofp/geometry";import{reaction as I}from"mobx";import{createImageDef as C,getBounds as b,rectToRenderer as F}from"../../../../renderer";import l,{layersStore as S}from"../../../../store";import{createImageCanvas as v}from"./canvases";const B="_selected";export const MARKER_LAYER_NAME="markers";export function configMarkers(s){const u=[],d=new Map,r=new Map;let n=[];const m=s.scene.rootLayer.children.find(t=>t.name===MARKER_LAYER_NAME);async function w(t){const o=[];t.forEach(a=>{const{name:e,content:i,width:c,height:g,scale:k}=a;if(d.has(e))return;const h=new Image,y=new Promise((D,M)=>{h.onload=()=>{d.set(e,{img:h,width:c,height:g,scale:k}),D()},h.onerror=x=>{M(x)}});o.push(y),h.src=i,h.crossOrigin="anonymous"}),await Promise.all(o)}const f=t=>`marker-ptScaleHandlers-${t.id}`,E=t=>`marker-rollHandlers-${t.id}`,P=(t,o)=>{s.onPtScale(o,a=>{const{center:e,rotation:i}=t.bounds,{width:c,height:g}=t.source;return t.bounds=F(b(e.x,e.y,c,g,a,i)),t})},H=(t,o)=>{s.onRoll(o,a=>(t.bounds.rotation=a,t))};function L(){const t=l.routeStore.markersData.markers;if(!t.length)return;n=[];const o=s.scale,a=T(s.angle);t.forEach(e=>{const i=d.get(e.icon);if(!i)return;const c=i.scale||window.devicePixelRatio,g=e.icon;if(!r.has(g)){const R=v(i.img,i.width,i.height,c);r.set(g,R)}const k=r.get(g),h=d.get(e.selectedIcon),y=e.selectedIcon;if(!r.has(y)){const R=v(h.img,h.width,h.height,c);r.set(y,R)}const D=r.get(y),M=S.findLayer(e.z)?.visible??!0,x=b(e.x,e.y,k.width,k.height,o,a),_=b(e.x,e.y,D.width,D.height,o,a);let p;switch(e.position){case"lefttop":p=[0,0];break;case"centertop":p=[.5,0];break;case"centerbottom":p=[.5,1];break;default:p=[.5,.5]}const z={...C(k,x,{hidden:!M,origin:p}),id:e.id,scale:c},A={...C(D,_,{hidden:!(M&&e.active),origin:p}),id:`${e.id}${B}`,scale:c};n.push(z,A)}),m.children=n,n.forEach(e=>{P(e,f(e)),H(e,E(e))})}function $(){n.forEach(t=>{s.ptScaleRegistry.unregisterByName(f(t)),s.rollRegistry.unregisterByName(E(t))}),m.children=[],n=[]}function N(){const t=l.routeStore.markersData.markers;t.length&&t.forEach(o=>{const a=n.find(c=>c.id===o.id),e=n.find(c=>c.id===`${o.id}${B}`);if(!a)return;const i=S.findLayer(o.z)?.visible??!0;o.active?(a.hidden=!0,e.hidden=!(i&&o.active)):(a.hidden=!i,e.hidden=!0)})}return u.push(I(()=>[l.routeStore.selectedMarkers,l.layerStore.visible],()=>{if(!l.routeStore.markersData.markers.length){$(),s.update(m);return}N(),s.update(...n)})),u.push(I(()=>l.routeStore.markersData.markers,()=>{w(l.routeStore.markersData.icons).then(()=>{L(),s.update(m)})},{fireImmediately:!0})),function(){u.forEach(o=>o()),u.length=0}}export function getMarkerFromClick(s,u,d){for(const r of l.routeStore.markersData.markers){const n=l.routeStore.markersData.icons.find(f=>f.name===r.icon);if(!n)continue;const m=n.width*d*devicePixelRatio,w=n.height*d*devicePixelRatio;if(O(s,u,r.x,r.y,m,w)){const f=l.layerStore.findLayer(r.z);if(!f||f&&f.visible)return r}}return null}function O(s,u,d,r,n,m){return K.fromCenter({x:d,y:r},{x:2*n,y:2*m}).containsPoint({x:s,y:u})}
1
+ import{Box as O}from"@expofp/geometry";import{update as D}from"@expofp/renderer";import{reaction as I}from"mobx";import{getBounds as w}from"../../../../engine/canvases";import{createImageDef as E}from"../../../../engine/defs";import u,{layersStore as C}from"../../../../store";import{setMarkerResolver as R}from"../../pointer";import{createImageCanvas as P}from"./canvases";const L="_selected";export const MARKER_LAYER_NAME="markers";function T(o,f){const{center:c,rotation:r}=o.bounds,{width:i,height:s}=o.source;return o.bounds=w(c.x,c.y,i,s,f,r),[o]}function W(o){B=o}export function configMarkers(o){const{scene:f}=o,c=[],r=new Map,i=new Map;let s=[];const a=f.rootLayer.children.find(e=>e.name===MARKER_LAYER_NAME);a.onScale=({pixelSize:e})=>W(e),R(markerAt),D(a);async function g(e){const n=[];e.forEach(m=>{const{name:t,content:d,width:l,height:k,scale:y}=m;if(r.has(t))return;const h=new Image,S=new Promise((v,M)=>{h.onload=()=>{r.set(t,{img:h,width:l,height:k,scale:y}),v()},h.onerror=b=>{M(b)}});n.push(S),h.src=d,h.crossOrigin="anonymous"}),await Promise.all(n)}const z=e=>{e.onScale=({pixelSize:n})=>T(e,n)},A=e=>{e.onRoll=({roll:n})=>{if(n!==e.bounds.rotation)return e.bounds.rotate(n-e.bounds.rotation,e.bounds),[e]}};function _(){const e=u.routeStore.markersData.markers;if(!e.length)return;s=[];const n=1,m=0;e.forEach(t=>{const d=r.get(t.icon);if(!d)return;const l=d.scale||window.devicePixelRatio,k=t.icon;if(!i.has(k)){const x=P(d.img,d.width,d.height,l);i.set(k,x)}const y=i.get(k),h=r.get(t.selectedIcon),S=t.selectedIcon;if(!i.has(S)){const x=P(h.img,h.width,h.height,l);i.set(S,x)}const v=i.get(S),M=C.findLayer(t.z)?.visible??!0,b=w(t.x,t.y,y.width,y.height,n,m),F=w(t.x,t.y,v.width,v.height,n,m);let p;switch(t.position){case"lefttop":p=[0,0];break;case"centertop":p=[.5,0];break;case"centerbottom":p=[.5,1];break;default:p=[.5,.5]}const H={...E(y,b,{hidden:!M,origin:p}),id:t.id,scale:l},N={...E(v,F,{hidden:!(M&&t.active),origin:p}),id:`${t.id}${L}`,scale:l};s.push(H,N)}),a.children=s,s.forEach(t=>{z(t),A(t)})}function $(){a.children=[],s=[]}function K(){const e=u.routeStore.markersData.markers;e.length&&e.forEach(n=>{const m=s.find(l=>l.id===n.id),t=s.find(l=>l.id===`${n.id}${L}`);if(!m)return;const d=C.findLayer(n.z)?.visible??!0;n.active?(m.hidden=!0,t.hidden=!(d&&n.active)):(m.hidden=!d,t.hidden=!0)})}return c.push(I(()=>[u.routeStore.selectedMarkers,u.layerStore.visible],()=>{if(!u.routeStore.markersData.markers.length){$(),D(a);return}K(),D(...s)})),c.push(I(()=>u.routeStore.markersData.markers,()=>{g(u.routeStore.markersData.icons).then(()=>{_(),D(a)})},{fireImmediately:!0})),function(){c.forEach(n=>n()),c.length=0,a.onScale=void 0,R(),D(a)}}export function markerAt(o,f){return getMarkerFromClick(o,f,B)}export function getMarkerFromClick(o,f,c){for(const r of u.routeStore.markersData.markers){const i=u.routeStore.markersData.icons.find(g=>g.name===r.icon);if(!i)continue;const s=i.width*c*devicePixelRatio,a=i.height*c*devicePixelRatio;if(Y(o,f,r.x,r.y,s,a)){const g=u.layerStore.findLayer(r.z);if(!g||g&&g.visible)return r}}return null}function Y(o,f,c,r,i,s){return O.fromCenter({x:c,y:r},{x:2*i,y:2*s}).containsPoint({x:o,y:f})}let B=1;
@@ -0,0 +1,35 @@
1
+ import { type ImageDef, type LayerDef } from '@expofp/renderer';
2
+ export interface ParentRectLike {
3
+ readonly center: {
4
+ readonly x: number;
5
+ readonly y: number;
6
+ };
7
+ readonly size: {
8
+ readonly x: number;
9
+ readonly y: number;
10
+ };
11
+ readonly rotation: number;
12
+ }
13
+ /** A loaded layer image, with the bounds of whatever it was placed inside. */
14
+ export interface ImageDefWithParentBounds {
15
+ parentRect?: ParentRectLike;
16
+ shape: ImageDef;
17
+ }
18
+ /** Loads one configured layer's designer images and hands back where they belong. */
19
+ export type LayerImagesHandler = () => Promise<{
20
+ layer: LayerDef;
21
+ children: ImageDefWithParentBounds[];
22
+ }>;
23
+ /**
24
+ * Registers a layer's image loader under its layer name.
25
+ * @param name - The image layer's name.
26
+ * @param handler - Loads the images.
27
+ * @returns A disposer removing this registration, unless a newer one replaced it.
28
+ */
29
+ export declare function registerLayerImages(name: string, handler: LayerImagesHandler): () => void;
30
+ /**
31
+ * Starts every registered loader.
32
+ * @returns One promise per registered layer.
33
+ */
34
+ export declare function invokeLayerImages(): ReturnType<LayerImagesHandler>[];
35
+ //# sourceMappingURL=layer-images.d.ts.map
@@ -0,0 +1 @@
1
+ const t=new Map;export function registerLayerImages(e,r){return t.set(e,r),()=>{t.get(e)===r&&t.delete(e)}}export function invokeLayerImages(){return[...t.values()].map(e=>e())}
@@ -1,12 +1,47 @@
1
1
  import { Rect } from '@expofp/geometry';
2
- import { RendererService } from '../../../../renderer';
2
+ import { ModelDef } from '@expofp/renderer';
3
3
  import { type Booth } from '../../../../store/BoothStore';
4
4
  import { type Layer } from '../../../../store/LayerStore';
5
5
  import { ImageUrls } from '../../../../utils/loadImagesInBatches';
6
- export declare function loadLayersImages(rendererService: RendererService): Promise<void>;
6
+ export declare function loadLayersImages(): Promise<void>;
7
7
  export declare const getImageLayerName: (layerName: string) => string;
8
+ export declare const getModelLayerName: (layerName: string) => string;
8
9
  export declare function mapBoothsLogos(booths: Booth[]): Map<number, ImageUrls>;
9
- export declare function getLayerIcons(layer: Layer): SVGImageElement[];
10
+ /** The attribute that turns a designer `<image>` into a 3D model: a relative URL to a .glb/.gltf. */
11
+ export declare const MODEL_3D_ATTRIBUTE = "data-model-3d";
12
+ /**
13
+ * A layer's designer images, split by what they actually are. An `<image>` carrying
14
+ * {@link MODEL_3D_ATTRIBUTE} is a placeholder for a 3D model, so it must be kept out of image
15
+ * loading entirely — its `href` is never fetched — and rendered from the model URL instead.
16
+ */
17
+ export interface LayerGraphics {
18
+ /** Ordinary images, to be loaded and drawn as textured quads. */
19
+ icons: SVGImageElement[];
20
+ /** Images standing in for 3D models. */
21
+ models: SVGImageElement[];
22
+ }
23
+ export declare function getLayerGraphics(layer: Layer): LayerGraphics;
24
+ /**
25
+ * The rotation an SVG graphic carries, in radians.
26
+ *
27
+ * Shared by icons and models so the two cannot drift. It inherits the assumption `loadIcons` has
28
+ * always made: an SVG `rotate(a, cx, cy)` is treated as pivoting about the element's own center,
29
+ * because that is what a geometry `Rect` does. A transform with a different pivot is placed wrongly —
30
+ * pre-existing behavior, recorded rather than fixed here.
31
+ * @param element - The graphic to read.
32
+ * @returns The rotation in radians, positive = clockwise.
33
+ */
34
+ export declare function graphicRotation(element: SVGGraphicsElement): number;
35
+ /**
36
+ * Builds a {@link ModelDef} from an `<image>` carrying {@link MODEL_3D_ATTRIBUTE}.
37
+ *
38
+ * Bounds come from the element's own x/y/width/height — `Box.fromSvg` reads an `<image>` as readily
39
+ * as a `<rect>` — combined with its transform's rotation. The URL is relative to the plan's data
40
+ * base, the same resolution ordinary image hrefs get.
41
+ * @param element - The placeholder image.
42
+ * @returns The model def.
43
+ */
44
+ export declare function createModelDefFromElement(element: SVGImageElement): ModelDef;
10
45
  export interface BoothImg {
11
46
  booth: Booth;
12
47
  name?: string;
@@ -1 +1 @@
1
- import{degToRad as f,radToDeg as d,Rect as h}from"@expofp/geometry";import{select as u}from"d3";import{SEPARATOR as y}from"../../../../constants";import{getFpSvgJs as R}from"../../../../data/fp-payloads";import{getLayerSvg as x}from"../../../../data/svg";import{flipImageDef as I,isInnerInsideOuter as w}from"../../../../renderer";import{rotateImageDef as A}from"../../../../renderer/engine-core/utils/rotation";import{getLogoUrl as L}from"../../../../utils/getLogoUrl";export async function loadLayersImages(e){const a=e.layerImagesRegistry.invoke();await Promise.all(a.map(async s=>{const n=await s;if(!n)return;const{layer:r,children:c}=n;if(c.length){const i=[];for(let o=0;o<c.length;o++){const{shape:t,parentRect:g}=c[o],l=w(t.bounds,g);if(!r.name.includes("Pathway_")){const m=l?"image-rotate":"image-flip";e.onRoll(`${m}-${r.name}-${o}`,l?p=>A(t,p):p=>I(t,p))}i.push(t)}r.children.push(...i),e.update(r)}}))}export const getImageLayerName=e=>`${e}${y}images`;export function mapBoothsLogos(e){return new Map(e.map(a=>{const s=a.rect&&a.exhibitors.find(n=>n.logoInBooth&&n.logo);return s?[a.id,{preferred:L(s.logo),fallback:s.logo.url}]:null}).filter(Boolean))}export function getLayerIcons(e){const a=u(x(e)).select(`[data-layer="${e.name}"]`);return(R().__fpVersion>5?a.selectAll(":scope > image, :scope > g:not([data-layer]) image").nodes():a.selectAll(":scope > g[data-is-editable='false'] image").nodes()).filter(Boolean)}export function createBoothImg(e,a){const s=e.rect,n=s.size.width,r=s.size.height,c=r?n/r:1,i=a.height?a.width/a.height:1;let o,t,g;const l=.9;c>i?(t=r*l,o=t*i):(o=n*l,t=o/i);const m=e.rotate||0;return i>=2&&!m&&r>=n*2?(t=n*l,o=t*i,g=-90):g=d(m),o>n&&(o=n,t=o/i),t>r&&(t=r,o=t*i),{name:e.slug,bounds:new h(s.center,{x:o,y:t},f(g)),htmlImage:a,booth:e}}
1
+ import{Box as u,degToRad as d,radToDeg as h,Rect as g}from"@expofp/geometry";import{update as x}from"@expofp/renderer";import{select as y}from"d3";import{SEPARATOR as p}from"../../../../constants";import{getFpSvgJs as R}from"../../../../data/fp-payloads";import{getLayerSvg as A}from"../../../../data/svg";import{flipImageDef as L,isInnerInsideOuter as w,rotateImageDef as B}from"../../../../engine/utils/rotation";import{getLogoUrl as T}from"../../../../utils/getLogoUrl";import{invokeLayerImages as _}from"./layer-images";export async function loadLayersImages(){const e=_();await Promise.all(e.map(async o=>{const r=await o;if(!r)return;const{layer:n,children:a}=r;if(a.length){const c=[];for(const s of a){const{shape:t,parentRect:i}=s,m=w(t.bounds,i);n.name.includes("Pathway_")||(t.onRoll=m?({roll:l})=>B(t,l)?[t]:void 0:({roll:l})=>L(t,l)?[t]:void 0),c.push(t)}n.children.push(...c),x(n)}}))}export const getImageLayerName=e=>`${e}${p}images`,getModelLayerName=e=>`${e}${p}models`;export function mapBoothsLogos(e){return new Map(e.map(o=>{const r=o.rect&&o.exhibitors.find(n=>n.logoInBooth&&n.logo);return r?[o.id,{preferred:T(r.logo),fallback:r.logo.url}]:null}).filter(Boolean))}export const MODEL_3D_ATTRIBUTE="data-model-3d";export function getLayerGraphics(e){const o=y(A(e)).select(`[data-layer="${e.name}"]`),r=(R().__fpVersion>5?o.selectAll(":scope > image, :scope > g:not([data-layer]) image").nodes():o.selectAll(":scope > g[data-is-editable='false'] image").nodes()).filter(Boolean),n=[],a=[];for(const c of r)(c.hasAttribute(MODEL_3D_ATTRIBUTE)?a:n).push(c);return{icons:n,models:a}}export function graphicRotation(e){return d(e.transform?.animVal[0]?.angle??0)}export function createModelDefFromElement(e){const o=u.fromSvg(e);return{url:D(e.getAttribute(MODEL_3D_ATTRIBUTE)),bounds:g.fromMinMax(o.min,o.max,graphicRotation(e))}}function D(e){return!e?.startsWith("data:")&&e?.indexOf("://")===-1?window.__dataUrlBase+e:e}export function createBoothImg(e,o){const r=e.rect,n=r.size.width,a=r.size.height,c=a?n/a:1,s=o.height?o.width/o.height:1;let t,i,m;const l=.9;c>s?(i=a*l,t=i*s):(t=n*l,i=t/s);const f=e.rotate||0;return s>=2&&!f&&a>=n*2?(i=n*l,t=i*s,m=-90):m=h(f),t>n&&(t=n,i=t/s),i>a&&(i=a,t=i*s),{name:e.slug,bounds:new g(r.center,{x:t,y:i},d(m),e.elevation),htmlImage:o,booth:e}}
@@ -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;