@expofp/floorplan 3.18.1 → 3.20.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 (95) hide show
  1. package/dist/browser/{Button-D24xOa4I.js → Button-Dam5jkfA.js} +5 -5
  2. package/dist/browser/{CookieConsent-BTzsoyoV.js → CookieConsent-_3c-4qfS.js} +7 -7
  3. package/dist/browser/{Debug-CqKhUi06.js → Debug-DkOOBGTk.js} +7 -7
  4. package/dist/browser/{Demo-B3EOY0Xq.js → Demo-DytKqzi1.js} +9 -9
  5. package/dist/browser/{Free-pY7M8m4h.js → Free-D7MSz49h.js} +9 -9
  6. package/dist/browser/{Gallery-A8cqqrTJ.js → Gallery-B3EQqw3g.js} +9 -9
  7. package/dist/browser/{GpsLoader-DpJhUdzw.js → GpsLoader-C3VOU-AX.js} +28 -28
  8. package/dist/browser/{KioskStore-DICU_c9W.js → KioskStore-xIgZM3_4.js} +7 -7
  9. package/dist/browser/{MaplibreAdapter-DDSPODNR.js → MaplibreAdapter-CLhcUeG3.js} +2268 -2027
  10. package/dist/browser/{ModalContainer-DnwGQgDt.js → ModalContainer-DO2w5iKD.js} +10 -10
  11. package/dist/browser/{PermissionNotice-Gw1lUPnc.js → PermissionNotice-DDhK_CzL.js} +6 -6
  12. package/dist/browser/{SetKioskMode-mh3piul9.js → SetKioskMode-C4GlSw75.js} +9 -9
  13. package/dist/browser/{ShowKiosk-zkF-CXr8.js → ShowKiosk-BiQL7KaN.js} +12 -12
  14. package/dist/browser/{TouchHand-DWec6Hd2.js → TouchHand--hyrm-pn.js} +4 -4
  15. package/dist/browser/{ViewerMenuPanel-C_wp1AsD.js → ViewerMenuPanel-yNp88UsQ.js} +10 -10
  16. package/dist/browser/{add-debug-secret-listener-DVLr6HP8.js → add-debug-secret-listener-wFMLV2Ik.js} +1 -1
  17. package/dist/browser/{adopt-global-settings-Btj0VnLn.js → adopt-global-settings-BcaNagH6.js} +9 -9
  18. package/dist/browser/{boolean-editor-BpIQdba3.js → boolean-editor-DmQ9hGwq.js} +9 -9
  19. package/dist/browser/{bootIntercom-DSg-Cxkq.js → bootIntercom-DgThK91j.js} +2 -2
  20. package/dist/browser/{booth-by-xy-BvNNTs6Q.js → booth-by-xy-m-WbKbVp.js} +296 -296
  21. package/dist/browser/bundle.json +66 -66
  22. package/dist/browser/{classnames-CFZOol_A.js → classnames-DuZoMrrx.js} +2 -2
  23. package/dist/browser/{client-BSrj7kzz.js → client-Dj9OWVha.js} +4 -4
  24. package/dist/browser/{components-6Db-nRo5.js → components-dk3NcsBa.js} +1364 -1364
  25. package/dist/browser/{debug-overlay-Bt6DNp-8.js → debug-overlay-CCtqp8lb.js} +10 -10
  26. package/dist/browser/{debug-ui-X9kyhrgx.js → debug-ui-DCJyeLAd.js} +6 -6
  27. package/dist/browser/{dist-CSjEqv2k.js → dist-CaujNaF9.js} +3 -3
  28. package/dist/browser/{dist-HS_i2V3o.js → dist-D2vwS61f.js} +6 -6
  29. package/dist/browser/{dist-H1U2_uEE.js → dist-DQaisR_W.js} +5 -5
  30. package/dist/browser/{efp-debug-init-D0_xHeMm.js → efp-debug-init-CHsd9_cw.js} +3 -3
  31. package/dist/browser/{enum-editor-Y3eY0GZN.js → enum-editor-Coez2npo.js} +4 -4
  32. package/dist/browser/{es5-Bnh-FuEf.js → es5-cNhUtAJ8.js} +2 -2
  33. package/dist/browser/{event-not-found-DaBAYGFy.js → event-not-found-B7qN6S0M.js} +1 -1
  34. package/dist/browser/{exports-pRH9fRPj.js → exports-BScyxu3S.js} +1 -1
  35. package/dist/browser/{favicon-eVAPrhqR.js → favicon-Dz0iIR93.js} +1 -1
  36. package/dist/browser/{fetch-retry.umd-CU86oApr.js → fetch-retry.umd-CtEKqYh8.js} +2 -2
  37. package/dist/browser/{flex-CBHNyrZ4.js → flex-CjUEJCJL.js} +5 -5
  38. package/dist/browser/{floorplan.loader-C2Uhu9rp.js → floorplan.loader-qT-UiIac.js} +19 -19
  39. package/dist/browser/{floorplan.ready-D1uAmP_v.js → floorplan.ready-CfSkG24j.js} +199 -199
  40. package/dist/browser/{fuse-N8kU4K-S.js → fuse-SCSXSIS7.js} +2 -2
  41. package/dist/browser/{i18n-BtP9mFz3.js → i18n-B6dEf7vu.js} +2425 -2369
  42. package/dist/browser/index.js +34 -34
  43. package/dist/browser/{index.module-BsJ6W9of.js → index.module-CkZa7zY4.js} +4 -4
  44. package/dist/browser/{integrateKiosk-3pSiw3dQ.js → integrateKiosk-Cd0gOtb9.js} +4 -4
  45. package/dist/browser/{is-webview-Cta8T4n3.js → is-webview-CPRfPICf.js} +1 -1
  46. package/dist/browser/{jsx-runtime-BEbKJk0I.js → jsx-runtime-BRhWrtmW.js} +2 -2
  47. package/dist/browser/{kiosk-record-CqwMLWxV.js → kiosk-record-cqqud1dq.js} +1 -1
  48. package/dist/browser/{lib-I9l3N_qn.js → lib-CujMS-mv.js} +3 -3
  49. package/dist/browser/{loadImage-Dss1EbV-.js → loadImage-DidrxJwE.js} +4 -4
  50. package/dist/browser/{logDeviceInfo-C71JR2gm.js → logDeviceInfo-BAhvfe0n.js} +9 -9
  51. package/dist/browser/{main-CfBwT8A1.js → main-YwrZTknD.js} +1 -1
  52. package/dist/browser/{mobx-BczBqzzL.js → mobx-BHYB6eG8.js} +4 -4
  53. package/dist/browser/{optional-boolean-editor-DzQfvreW.js → optional-boolean-editor-3Q_rCrSw.js} +3 -3
  54. package/dist/browser/{optional-enum-editor-CLMliNto.js → optional-enum-editor-DIBHKeL9.js} +4 -4
  55. package/dist/browser/{optional-string-editor-_KGdUVEY.js → optional-string-editor-BOWeJ5Vg.js} +4 -4
  56. package/dist/browser/{particles.min-B1MXziWd.js → particles.min-HJq3ka3X.js} +2 -2
  57. package/dist/browser/{react-dom-Cw00D2pA.js → react-dom-D8-OMRDw.js} +3 -3
  58. package/dist/browser/{react-DGnrgmGu.js → react-lDheuaid.js} +2 -2
  59. package/dist/browser/{rolldown-runtime-BwZ60izJ.js → rolldown-runtime-7-Wh3Cc7.js} +1 -1
  60. package/dist/browser/{select-D1YJPbva.js → select-DvPNhCF6.js} +10 -10
  61. package/dist/browser/{settings-Bi32JyQ7.js → settings-D-p69PHO.js} +2 -2
  62. package/dist/browser/{settings-item-SFeXQJg_.js → settings-item-CAMlHscI.js} +6 -6
  63. package/dist/browser/{store-D3AM4bNd.js → store-Dh-bVjb-.js} +6371 -6230
  64. package/dist/browser/{string-editor-CDi_Yy04.js → string-editor-C4Fg-qxc.js} +4 -4
  65. package/dist/browser/{text-field-BtEculxh.js → text-field-DHhTARyo.js} +5 -5
  66. package/dist/browser/{theme-DDvtl3pp.js → theme-B72VWXzW.js} +8 -8
  67. package/dist/browser/{ui-xJEwvFPJ.js → ui-CibYpqSJ.js} +8 -8
  68. package/dist/browser/{useRenderTarget-Cswo9eRB.js → useRenderTarget-DAy71car.js} +4 -4
  69. package/dist/esm/components/Map/drawing/config/canvases.d.ts +9 -0
  70. package/dist/esm/components/Map/drawing/config/canvases.js +1 -1
  71. package/dist/esm/components/Map/drawing/config/config-load-layer.js +1 -1
  72. package/dist/esm/components/Map/drawing/config/config-outdoor-poi.d.ts +31 -0
  73. package/dist/esm/components/Map/drawing/config/config-outdoor-poi.js +1 -0
  74. package/dist/esm/components/Maplibre/MaplibreAdapter.js +1 -1
  75. package/dist/esm/components/Maplibre/useCameraReactions.js +1 -1
  76. package/dist/esm/components/Maplibre/useDimming.d.ts +9 -0
  77. package/dist/esm/components/Maplibre/useDimming.js +1 -1
  78. package/dist/esm/components/Maplibre/usePoiMarkers.d.ts +26 -0
  79. package/dist/esm/components/Maplibre/usePoiMarkers.js +1 -0
  80. package/dist/esm/components/Maplibre/useRendererEvents.js +1 -1
  81. package/dist/esm/components/Maplibre/utils/geo-config.d.ts +2 -0
  82. package/dist/esm/components/Maplibre/utils/geo-config.js +1 -1
  83. package/dist/esm/components/Maplibre/utils/poi-marker-hit-test.d.ts +16 -0
  84. package/dist/esm/components/Maplibre/utils/poi-marker-hit-test.js +1 -0
  85. package/dist/esm/constants.d.ts +11 -0
  86. package/dist/esm/constants.js +1 -1
  87. package/dist/esm/services/url-sync.d.ts +1 -1
  88. package/dist/esm/services/url-sync.js +1 -1
  89. package/dist/esm/store/PoiMarkerStore.d.ts +76 -0
  90. package/dist/esm/store/PoiMarkerStore.js +1 -0
  91. package/dist/esm/store/RootStore.d.ts +2 -0
  92. package/dist/esm/store/RootStore.js +1 -1
  93. package/dist/esm/store/outdoor-poi-filter.d.ts +21 -0
  94. package/dist/esm/store/outdoor-poi-filter.js +1 -0
  95. package/package.json +8 -8
@@ -1,14 +1,14 @@
1
1
  (function() {
2
2
  try {
3
3
  var e = typeof window < "u" ? window : typeof global < "u" ? global : typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : {};
4
- e.SENTRY_RELEASE = { id: "3.18.1" };
4
+ e.SENTRY_RELEASE = { id: "3.20.0" };
5
5
  var t = new e.Error().stack;
6
6
  t && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[t] = "0a67f4c1-0ef6-428f-92c6-94c57178bf21", e._sentryDebugIdIdentifier = "sentry-dbid-0a67f4c1-0ef6-428f-92c6-94c57178bf21");
7
7
  } catch {}
8
8
  })();
9
- import { t as e } from "./jsx-runtime-BEbKJk0I.js";
10
- import { t } from "./settings-item-SFeXQJg_.js";
11
- import { t as n } from "./text-field-BtEculxh.js";
9
+ import { t as e } from "./jsx-runtime-BRhWrtmW.js";
10
+ import { t } from "./settings-item-CAMlHscI.js";
11
+ import { t as n } from "./text-field-DHhTARyo.js";
12
12
  //#region ../debug/src/lib/ui/string-editor.tsx
13
13
  var r = e(), i = (e) => {
14
14
  var i;
@@ -1,15 +1,15 @@
1
1
  (function() {
2
2
  try {
3
3
  var e = typeof window < "u" ? window : typeof global < "u" ? global : typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : {};
4
- e.SENTRY_RELEASE = { id: "3.18.1" };
4
+ e.SENTRY_RELEASE = { id: "3.20.0" };
5
5
  var t = new e.Error().stack;
6
6
  t && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[t] = "9c5a0877-c176-4e2d-b51c-123d50ab2b3c", e._sentryDebugIdIdentifier = "sentry-dbid-9c5a0877-c176-4e2d-b51c-123d50ab2b3c");
7
7
  } catch {}
8
8
  })();
9
- import { r as e } from "./rolldown-runtime-BwZ60izJ.js";
10
- import { t } from "./react-DGnrgmGu.js";
11
- import { D as n, i as r, l as i, n as a, s as o, u as s, y as c } from "./flex-CBHNyrZ4.js";
12
- import { t as l } from "./classnames-CFZOol_A.js";
9
+ import { r as e } from "./rolldown-runtime-7-Wh3Cc7.js";
10
+ import { t } from "./react-lDheuaid.js";
11
+ import { D as n, i as r, l as i, n as a, s as o, u as s, y as c } from "./flex-CjUEJCJL.js";
12
+ import { t as l } from "./classnames-DuZoMrrx.js";
13
13
  //#region ../../node_modules/.pnpm/@radix-ui+themes@3.3.0_@types+react-dom@19.2.3_@types+react@19.2.17__@types+react@19.2._5ea800d4e947acedb1fa1275f1697b17/node_modules/@radix-ui/themes/dist/esm/components/text-field.props.js
14
14
  var u = /* @__PURE__ */ e(t()), d = /* @__PURE__ */ e(l()), f = {
15
15
  size: {
@@ -1,18 +1,18 @@
1
1
  (function() {
2
2
  try {
3
3
  var e = typeof window < "u" ? window : typeof global < "u" ? global : typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : {};
4
- e.SENTRY_RELEASE = { id: "3.18.1" };
4
+ e.SENTRY_RELEASE = { id: "3.20.0" };
5
5
  var t = new e.Error().stack;
6
6
  t && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[t] = "f658045a-5be7-4ea4-a4b2-ddea9ab9caf3", e._sentryDebugIdIdentifier = "sentry-dbid-f658045a-5be7-4ea4-a4b2-ddea9ab9caf3");
7
7
  } catch {}
8
8
  })();
9
- import { r as e } from "./rolldown-runtime-BwZ60izJ.js";
10
- import { t } from "./react-DGnrgmGu.js";
11
- import { t as n } from "./jsx-runtime-BEbKJk0I.js";
12
- import { t as r } from "./react-dom-Cw00D2pA.js";
13
- import { C as i, E as a, O as o, T as s, _ as c, o as l, v as u, w as d } from "./flex-CBHNyrZ4.js";
14
- import { c as f, i as p, n as m, o as h, r as g, s as _, t as v } from "./dist-HS_i2V3o.js";
15
- import { t as y } from "./classnames-CFZOol_A.js";
9
+ import { r as e } from "./rolldown-runtime-7-Wh3Cc7.js";
10
+ import { t } from "./react-lDheuaid.js";
11
+ import { t as n } from "./jsx-runtime-BRhWrtmW.js";
12
+ import { t as r } from "./react-dom-D8-OMRDw.js";
13
+ import { C as i, E as a, O as o, T as s, _ as c, o as l, v as u, w as d } from "./flex-CjUEJCJL.js";
14
+ import { c as f, i as p, n as m, o as h, r as g, s as _, t as v } from "./dist-D2vwS61f.js";
15
+ import { t as y } from "./classnames-DuZoMrrx.js";
16
16
  //#region ../../node_modules/.pnpm/@radix-ui+react-visually-hidden@1.2.3_@types+react-dom@19.2.3_@types+react@19.2.17__@ty_cffccd7838985066e8e1d993b5cb6017/node_modules/@radix-ui/react-visually-hidden/dist/index.mjs
17
17
  var b = /* @__PURE__ */ e(r(), 1), x = /* @__PURE__ */ e(t(), 1), S = n(), C = Object.freeze({
18
18
  position: "absolute",
@@ -1,17 +1,17 @@
1
1
  (function() {
2
2
  try {
3
3
  var e = typeof window < "u" ? window : typeof global < "u" ? global : typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : {};
4
- e.SENTRY_RELEASE = { id: "3.18.1" };
4
+ e.SENTRY_RELEASE = { id: "3.20.0" };
5
5
  var t = new e.Error().stack;
6
6
  t && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[t] = "3c34ab8b-5d65-4c06-8595-6ed371acabc5", e._sentryDebugIdIdentifier = "sentry-dbid-3c34ab8b-5d65-4c06-8595-6ed371acabc5");
7
7
  } catch {}
8
8
  })();
9
- import { r as e } from "./rolldown-runtime-BwZ60izJ.js";
10
- import { a as t, i as n, s as r } from "./efp-debug-init-D0_xHeMm.js";
11
- import { a as i, i as a } from "./adopt-global-settings-Btj0VnLn.js";
12
- import { t as o } from "./jsx-runtime-BEbKJk0I.js";
13
- import "./settings-Bi32JyQ7.js";
14
- import { t as s } from "./add-debug-secret-listener-DVLr6HP8.js";
9
+ import { r as e } from "./rolldown-runtime-7-Wh3Cc7.js";
10
+ import { a as t, i as n, s as r } from "./efp-debug-init-CHsd9_cw.js";
11
+ import { a as i, i as a } from "./adopt-global-settings-BcaNagH6.js";
12
+ import { t as o } from "./jsx-runtime-BRhWrtmW.js";
13
+ import "./settings-D-p69PHO.js";
14
+ import { t as s } from "./add-debug-secret-listener-wFMLV2Ik.js";
15
15
  //#region ../debug/src/lib/ui/render-debug-ui.tsx
16
16
  var c = /* @__PURE__ */ e(r(), 1), l = o(), u = !1;
17
17
  function d() {
@@ -26,7 +26,7 @@ function d() {
26
26
  }
27
27
  });
28
28
  let o = async (t) => {
29
- let { DebugUi: n } = await import("./debug-ui-X9kyhrgx.js"), { createRoot: i } = await import("./client-BSrj7kzz.js").then((t) => /* @__PURE__ */ e(t.default, 1)), a = document.createElement("div");
29
+ let { DebugUi: n } = await import("./debug-ui-DCJyeLAd.js"), { createRoot: i } = await import("./client-Dj9OWVha.js").then((t) => /* @__PURE__ */ e(t.default, 1)), a = document.createElement("div");
30
30
  document.body.appendChild(a), i(a).render(/* @__PURE__ */ (0, l.jsx)(n, {
31
31
  useDebugButtonState: r.useState,
32
32
  open: t
@@ -1,14 +1,14 @@
1
1
  (function() {
2
2
  try {
3
3
  var e = typeof window < "u" ? window : typeof global < "u" ? global : typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : {};
4
- e.SENTRY_RELEASE = { id: "3.18.1" };
4
+ e.SENTRY_RELEASE = { id: "3.20.0" };
5
5
  var t = new e.Error().stack;
6
6
  t && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[t] = "a7e05aea-745e-4a4b-ba82-432527d9c312", e._sentryDebugIdIdentifier = "sentry-dbid-a7e05aea-745e-4a4b-ba82-432527d9c312");
7
7
  } catch {}
8
8
  })();
9
- import { r as e } from "./rolldown-runtime-BwZ60izJ.js";
10
- import { t } from "./react-DGnrgmGu.js";
11
- import { c as n } from "./store-D3AM4bNd.js";
9
+ import { r as e } from "./rolldown-runtime-7-Wh3Cc7.js";
10
+ import { t } from "./react-lDheuaid.js";
11
+ import { c as n } from "./store-Dh-bVjb-.js";
12
12
  //#region src/utils/getRenderTargetFromRoot.ts
13
13
  var r = /* @__PURE__ */ e(t(), 1);
14
14
  function i(e) {
@@ -4,5 +4,14 @@ export declare function createTargetCanvas(pixelRatio: number, color?: string, s
4
4
  export declare function createArrowCurrentCanvas(pixelRatio: number, color?: string, scale?: number): HTMLCanvasElement;
5
5
  export declare function createYahCanvas(pixelRatio: number, color?: string, scale?: number): HTMLCanvasElement;
6
6
  export declare function createLabelCanvas(text: string, fontSize: number, pixelRatio: number, color: string | undefined, fontWeight: number, strokeStyle?: string, strokeWidth?: number): HTMLCanvasElement;
7
+ /**
8
+ * The category pin for one outdoor PoI: the poiType glyph knocked out in white
9
+ * inside a pin filled with the booth's authored color. Returns `ImageData`
10
+ * rather than a canvas — the only consumer is `map.addImage`, and a canvas per
11
+ * PoI would stay resident for the session.
12
+ */
13
+ export declare function createPoiPinImage(image: HTMLImageElement | null, widthPx: number, pixelRatio: number, color: string): ImageData;
14
+ /** The shared selection pinhead — one image serves every marker. */
15
+ export declare function createPoiPinheadImage(size: number, pixelRatio: number, color: string): ImageData;
7
16
  export declare function getFont(px: number, weight?: number, style?: string): string;
8
17
  //# sourceMappingURL=canvases.d.ts.map
@@ -1 +1 @@
1
- import{FONT_FACE as z,FONT_WEIGHT_PRIMARY_BOOTH as f}from"../../../../constants";export function createImageCanvas(n,l,r,i,c=1,o){const e=n?n.width/n.height:1;let a=l*i*c,t=r*i*c;l/r>e?a=t*e:t=a/e;const v=document.createElement("canvas"),u=v.getContext("2d");return v.width=a,v.height=t,v.id=n.id,o==="horizontal"?(u.scale(-1,1),u.translate(-a,0)):o==="vertical"&&(u.scale(1,-1),u.translate(0,-t)),u.drawImage(n,0,0,a,t),v}export function createCurrentCanvas(n,l="#c8248b",r=n*.4,i,c,o,e="#000"){i=i||95,c=c||95;const a=document.createElement("canvas"),t=a.getContext("2d");a.width=i*r,a.height=c*r,t.scale(r,r);const v=i/2,u=c/2;if(t.translate(v-35,o?0:u-35),t.beginPath(),t.fillStyle="#FFFFFF",t.moveTo(0,35),t.bezierCurveTo(0,54.329966,15.670034,70,35,70),t.bezierCurveTo(54.329966,70,70,54.329966,70,35),t.bezierCurveTo(70,15.670034,54.329966,0,35,0),t.bezierCurveTo(15.670034,0,0,15.670034,0,35),t.fill(),t.beginPath(),t.fillStyle=l,t.moveTo(10,35),t.bezierCurveTo(10,48.807119,21.192881,60,35,60),t.bezierCurveTo(48.807119,60,60,48.807119,60,35),t.bezierCurveTo(60,21.192881,48.807119,10,35,10),t.bezierCurveTo(21.192881,10,10,21.192881,10,35),t.fill(),o){t.textAlign="center",t.textBaseline="alphabetic",t.lineJoin="round",t.strokeStyle="#fff",t.fillStyle=e;const T=38;t.font=getFont(T),t.lineWidth=6;const b=70+T;t.strokeText(o,35,b,i),t.fillText(o,35,b,i)}return a}export function createTargetCanvas(n,l="#c8248b",r=n*.5){const i=70*r,c=100*r,o=document.createElement("canvas"),e=o.getContext("2d");return o.width=i,o.height=c,e.scale(r,r),e.beginPath(),e.fillStyle="rgb(255, 255, 255)",e.moveTo(32.6,97.8),e.bezierCurveTo(24.4,81.5,0,57,0,32.6),e.bezierCurveTo(0,14.6,14.6,0,32.6,0),e.bezierCurveTo(50.5,0,65.2,14.6,65.2,32.6),e.bezierCurveTo(65.2,57,40.7,81.5,32.6,97.8),e.fill(),e.beginPath(),e.fillStyle=l,e.moveTo(32.6,91.1),e.bezierCurveTo(25.2,76.3,3.1,54.2,3.1,32.1),e.bezierCurveTo(3.1,15.9,16.3,2.6,32.6,2.6),e.bezierCurveTo(48.8,2.6,62,15.9,62,32.1),e.bezierCurveTo(62,54.2,39.9,76.3,32.6,91.1),e.fill(),e.beginPath(),e.fillStyle="rgb(255, 255, 255)",e.moveTo(16.2,32.6),e.bezierCurveTo(16.2,41.6,23.5,48.9,32.5,48.9),e.bezierCurveTo(41.5,48.9,48.8,41.6,48.8,32.6),e.bezierCurveTo(48.8,23.6,41.5,16.3,32.5,16.3),e.bezierCurveTo(23.5,16.3,16.2,23.6,16.2,32.6),e.fill(),o}export function createArrowCurrentCanvas(n,l="#c8248b",r=n*.4){const i=95*r,c=95*r,o=document.createElement("canvas"),e=o.getContext("2d");return o.width=i,o.height=c,e.scale(r,r),e.beginPath(),e.arc(47,47,25,0,2*Math.PI),e.fillStyle=l,e.fill(),e.beginPath(),e.fillStyle=l,e.moveTo(75,27),e.lineTo(95,47),e.lineTo(75,67),e.lineTo(80,47),e.closePath(),e.fill(),o}export function createYahCanvas(n,l="#ff4343",r=n*.5){const i=77*r,c=116*r,o=document.createElement("canvas"),e=o.getContext("2d");return o.width=i,o.height=c,e.scale(r,r),e.scale(r,r),e.beginPath(),e.fillStyle="#FFFFFF",e.moveTo(68.303,57.335),e.bezierCurveTo(77.894,39.304,70.649,15.785,50.95,8.04),e.bezierCurveTo(30.727,0,8.375,11.837,3.207,32.831),e.bezierCurveTo(0,46.185,6.644,57.323,13.131,68.211),e.fill(),e.beginPath(),e.fillStyle=l,e.moveTo(51.565,35.459),e.bezierCurveTo(51.565,43.256,45.201,49.575,37.354,49.575),e.bezierCurveTo(29.516,49.575,23.159,43.256,23.159,35.459),e.bezierCurveTo(23.159,27.668,29.516,21.345,37.354,21.345),e.bezierCurveTo(45.201,21.345,51.565,27.668,51.565,35.459),e.closePath(),e.fill(),e.beginPath(),e.moveTo(68.303,57.335),e.bezierCurveTo(77.894,39.304,70.649,15.785,50.95,8.04),e.bezierCurveTo(30.727,0,8.375,11.837,3.207,32.831),e.bezierCurveTo(0,46.185,6.644,57.323,13.131,68.211),e.lineTo(13.131,68.211),e.lineTo(13.131,68.211),e.bezierCurveTo(13.921,69.533,14.698,70.829,15.454,72.137),e.bezierCurveTo(19.465,79.158,23.533,86.12,27.571,93.086),e.lineTo(27.571,93.086),e.bezierCurveTo(30.098,97.421,32.611,101.756,35.116,106.077),e.bezierCurveTo(36.128,107.868,38.934,107.868,39.945,106.077),e.bezierCurveTo(49.387,90.003,58.708,74.029,68.031,57.951),e.bezierCurveTo(68.15,57.743,68.24,57.543,68.303,57.335),e.closePath(),e.moveTo(60.103,60.395),e.lineTo(63.201,55.041),e.lineTo(63.201,55.041),e.bezierCurveTo(73.31,36.735,61.285,11.614,39.04,11.17),e.bezierCurveTo(19.388,10.714,2.759,29.479,9.386,49.013),e.bezierCurveTo(10.726,52.998,12.657,56.9,14.84,60.721),e.bezierCurveTo(15.041,58.454,15.938,56.258,17.589,54.586),e.bezierCurveTo(19.708,52.425,22.216,50.638,24.996,49.283),e.bezierCurveTo(28.252,52.249,32.595,54.051,37.354,54.051),e.bezierCurveTo(42.123,54.051,46.47,52.249,49.73,49.283),e.bezierCurveTo(52.505,50.638,55.017,52.425,57.135,54.586),e.bezierCurveTo(58.701,56.188,59.701,58.245,60.103,60.395),e.closePath(),e.fill("evenodd"),e.beginPath(),e.moveTo(29.024,104.982),e.bezierCurveTo(29.024,103.626,27.923,102.527,26.57,102.527),e.bezierCurveTo(25.214,102.527,24.114,103.626,24.114,104.982),e.bezierCurveTo(24.114,111.395,30.347,116.838,37.444,116.838),e.bezierCurveTo(44.54,116.838,50.771,111.395,50.771,104.982),e.bezierCurveTo(50.771,103.626,49.666,102.527,48.317,102.527),e.bezierCurveTo(46.961,102.527,45.855,103.626,45.855,104.982),e.bezierCurveTo(45.855,108.193,42.352,111.956,37.444,111.956),e.bezierCurveTo(32.528,111.956,29.024,108.193,29.024,104.982),e.closePath(),e.fill(),o}const h=document.createElement("canvas"),C=h.getContext("2d");let d;function g(n,l){return d!==n&&(C.font=n),C.measureText(l).width}export function createLabelCanvas(n,l,r,i="#fff",c,o,e){n=n.replace(/^_/,""),l*=r;const a=document.createElement("canvas"),t=a.getContext("2d"),v=Number(getComputedStyle(document.body).getPropertyValue(f)),u=getFont(l,v||c),T=g(u,n.replace(/[0-9]/g,"3").replace(/[A-Z]/g,"A"))+3+3,b=4,s=l+b;return a.width=T*r,a.height=s*r,t.font=u,t.textAlign="center",t.textBaseline="alphabetic",t.fillStyle=i,e&&o&&(t.lineWidth=e,t.strokeStyle=o,t.strokeText(n,T/2,s-b/2*r),t.lineJoin="round"),t.fillText(n,T/2,s-b/2*r),a}export function getFont(n,l=500,r="normal"){const i=getComputedStyle(document.body).getPropertyValue(z),c='Oswald, -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',o=i?`${i}, ${c}`:c;return`${r} ${l} ${n}px ${o}`}
1
+ import{FONT_FACE as z,FONT_WEIGHT_PRIMARY_BOOTH as d}from"../../../../constants";export function createImageCanvas(i,l,r,o,c=1,n){const e=i?i.width/i.height:1;let a=l*o*c,t=r*o*c;l/r>e?a=t*e:t=a/e;const u=document.createElement("canvas"),s=u.getContext("2d");return u.width=a,u.height=t,u.id=i.id,n==="horizontal"?(s.scale(-1,1),s.translate(-a,0)):n==="vertical"&&(s.scale(1,-1),s.translate(0,-t)),s.drawImage(i,0,0,a,t),u}export function createCurrentCanvas(i,l="#c8248b",r=i*.4,o,c,n,e="#000"){o=o||95,c=c||95;const a=document.createElement("canvas"),t=a.getContext("2d");a.width=o*r,a.height=c*r,t.scale(r,r);const u=o/2,s=c/2;if(t.translate(u-35,n?0:s-35),t.beginPath(),t.fillStyle="#FFFFFF",t.moveTo(0,35),t.bezierCurveTo(0,54.329966,15.670034,70,35,70),t.bezierCurveTo(54.329966,70,70,54.329966,70,35),t.bezierCurveTo(70,15.670034,54.329966,0,35,0),t.bezierCurveTo(15.670034,0,0,15.670034,0,35),t.fill(),t.beginPath(),t.fillStyle=l,t.moveTo(10,35),t.bezierCurveTo(10,48.807119,21.192881,60,35,60),t.bezierCurveTo(48.807119,60,60,48.807119,60,35),t.bezierCurveTo(60,21.192881,48.807119,10,35,10),t.bezierCurveTo(21.192881,10,10,21.192881,10,35),t.fill(),n){t.textAlign="center",t.textBaseline="alphabetic",t.lineJoin="round",t.strokeStyle="#fff",t.fillStyle=e;const v=38;t.font=getFont(v),t.lineWidth=6;const T=70+v;t.strokeText(n,35,T,o),t.fillText(n,35,T,o)}return a}export function createTargetCanvas(i,l="#c8248b",r=i*.5){const o=70*r,c=100*r,n=document.createElement("canvas"),e=n.getContext("2d");return n.width=o,n.height=c,e.scale(r,r),e.beginPath(),e.fillStyle="rgb(255, 255, 255)",e.moveTo(32.6,97.8),e.bezierCurveTo(24.4,81.5,0,57,0,32.6),e.bezierCurveTo(0,14.6,14.6,0,32.6,0),e.bezierCurveTo(50.5,0,65.2,14.6,65.2,32.6),e.bezierCurveTo(65.2,57,40.7,81.5,32.6,97.8),e.fill(),e.beginPath(),e.fillStyle=l,e.moveTo(32.6,91.1),e.bezierCurveTo(25.2,76.3,3.1,54.2,3.1,32.1),e.bezierCurveTo(3.1,15.9,16.3,2.6,32.6,2.6),e.bezierCurveTo(48.8,2.6,62,15.9,62,32.1),e.bezierCurveTo(62,54.2,39.9,76.3,32.6,91.1),e.fill(),e.beginPath(),e.fillStyle="rgb(255, 255, 255)",e.moveTo(16.2,32.6),e.bezierCurveTo(16.2,41.6,23.5,48.9,32.5,48.9),e.bezierCurveTo(41.5,48.9,48.8,41.6,48.8,32.6),e.bezierCurveTo(48.8,23.6,41.5,16.3,32.5,16.3),e.bezierCurveTo(23.5,16.3,16.2,23.6,16.2,32.6),e.fill(),n}export function createArrowCurrentCanvas(i,l="#c8248b",r=i*.4){const o=95*r,c=95*r,n=document.createElement("canvas"),e=n.getContext("2d");return n.width=o,n.height=c,e.scale(r,r),e.beginPath(),e.arc(47,47,25,0,2*Math.PI),e.fillStyle=l,e.fill(),e.beginPath(),e.fillStyle=l,e.moveTo(75,27),e.lineTo(95,47),e.lineTo(75,67),e.lineTo(80,47),e.closePath(),e.fill(),n}export function createYahCanvas(i,l="#ff4343",r=i*.5){const o=77*r,c=116*r,n=document.createElement("canvas"),e=n.getContext("2d");return n.width=o,n.height=c,e.scale(r,r),e.scale(r,r),e.beginPath(),e.fillStyle="#FFFFFF",e.moveTo(68.303,57.335),e.bezierCurveTo(77.894,39.304,70.649,15.785,50.95,8.04),e.bezierCurveTo(30.727,0,8.375,11.837,3.207,32.831),e.bezierCurveTo(0,46.185,6.644,57.323,13.131,68.211),e.fill(),e.beginPath(),e.fillStyle=l,e.moveTo(51.565,35.459),e.bezierCurveTo(51.565,43.256,45.201,49.575,37.354,49.575),e.bezierCurveTo(29.516,49.575,23.159,43.256,23.159,35.459),e.bezierCurveTo(23.159,27.668,29.516,21.345,37.354,21.345),e.bezierCurveTo(45.201,21.345,51.565,27.668,51.565,35.459),e.closePath(),e.fill(),e.beginPath(),e.moveTo(68.303,57.335),e.bezierCurveTo(77.894,39.304,70.649,15.785,50.95,8.04),e.bezierCurveTo(30.727,0,8.375,11.837,3.207,32.831),e.bezierCurveTo(0,46.185,6.644,57.323,13.131,68.211),e.lineTo(13.131,68.211),e.lineTo(13.131,68.211),e.bezierCurveTo(13.921,69.533,14.698,70.829,15.454,72.137),e.bezierCurveTo(19.465,79.158,23.533,86.12,27.571,93.086),e.lineTo(27.571,93.086),e.bezierCurveTo(30.098,97.421,32.611,101.756,35.116,106.077),e.bezierCurveTo(36.128,107.868,38.934,107.868,39.945,106.077),e.bezierCurveTo(49.387,90.003,58.708,74.029,68.031,57.951),e.bezierCurveTo(68.15,57.743,68.24,57.543,68.303,57.335),e.closePath(),e.moveTo(60.103,60.395),e.lineTo(63.201,55.041),e.lineTo(63.201,55.041),e.bezierCurveTo(73.31,36.735,61.285,11.614,39.04,11.17),e.bezierCurveTo(19.388,10.714,2.759,29.479,9.386,49.013),e.bezierCurveTo(10.726,52.998,12.657,56.9,14.84,60.721),e.bezierCurveTo(15.041,58.454,15.938,56.258,17.589,54.586),e.bezierCurveTo(19.708,52.425,22.216,50.638,24.996,49.283),e.bezierCurveTo(28.252,52.249,32.595,54.051,37.354,54.051),e.bezierCurveTo(42.123,54.051,46.47,52.249,49.73,49.283),e.bezierCurveTo(52.505,50.638,55.017,52.425,57.135,54.586),e.bezierCurveTo(58.701,56.188,59.701,58.245,60.103,60.395),e.closePath(),e.fill("evenodd"),e.beginPath(),e.moveTo(29.024,104.982),e.bezierCurveTo(29.024,103.626,27.923,102.527,26.57,102.527),e.bezierCurveTo(25.214,102.527,24.114,103.626,24.114,104.982),e.bezierCurveTo(24.114,111.395,30.347,116.838,37.444,116.838),e.bezierCurveTo(44.54,116.838,50.771,111.395,50.771,104.982),e.bezierCurveTo(50.771,103.626,49.666,102.527,48.317,102.527),e.bezierCurveTo(46.961,102.527,45.855,103.626,45.855,104.982),e.bezierCurveTo(45.855,108.193,42.352,111.956,37.444,111.956),e.bezierCurveTo(32.528,111.956,29.024,108.193,29.024,104.982),e.closePath(),e.fill(),n}const m=document.createElement("canvas"),f=m.getContext("2d");let P;function y(i,l){return P!==i&&(f.font=i),f.measureText(l).width}export function createLabelCanvas(i,l,r,o="#fff",c,n,e){i=i.replace(/^_/,""),l*=r;const a=document.createElement("canvas"),t=a.getContext("2d"),u=Number(getComputedStyle(document.body).getPropertyValue(d)),s=getFont(l,u||c),v=y(s,i.replace(/[0-9]/g,"3").replace(/[A-Z]/g,"A"))+3+3,T=4,C=l+T;return a.width=v*r,a.height=C*r,t.font=s,t.textAlign="center",t.textBaseline="alphabetic",t.fillStyle=o,e&&n&&(t.lineWidth=e,t.strokeStyle=n,t.strokeText(i,v/2,C-T/2*r),t.lineJoin="round"),t.fillText(i,v/2,C-T/2*r),a}function S(i,l,r,o,c){const n=l/2,e=o+c,a=r-c;i.beginPath(),i.moveTo(n,a),i.bezierCurveTo(n-o*.55,e+o*.8,n-o,e+o*.35,n-o,e),i.bezierCurveTo(n-o,e-o*.72,n-o*.45,e-o,n,e-o),i.bezierCurveTo(n+o*.45,e-o,n+o,e-o*.72,n+o,e),i.bezierCurveTo(n+o,e+o*.35,n+o*.55,e+o*.8,n,a),i.closePath()}const b="#ffffff",F=93/81,x=125/90;function h(i,l,r,o,c,n){const e=i,a=i*l,t=document.createElement("canvas"),u=t.getContext("2d");t.width=e*r,t.height=a*r,u.scale(r,r);const s=e*o;return S(u,e,a,s,c),u.fillStyle=n,u.strokeStyle=b,u.lineWidth=c,u.lineJoin="round",u.fill(),u.stroke(),{canvas:t,ctx:u,cx:e/2,cy:s+c,r:s}}function g(i){return i.getContext("2d").getImageData(0,0,i.width,i.height)}export function createPoiPinImage(i,l,r,o){const{canvas:c,ctx:n,cx:e,cy:a}=h(l,F,r,.37,2,o);if(i){const t=createImageCanvas(i,l*.42,l*.42,r),u=t.getContext("2d");u.globalCompositeOperation="source-in",u.fillStyle=b,u.fillRect(0,0,t.width,t.height);const s=t.width/r,v=t.height/r;n.drawImage(t,e-s/2,a-v/2,s,v)}return g(c)}export function createPoiPinheadImage(i,l,r){const{canvas:o,ctx:c,cx:n,cy:e,r:a}=h(i,x,l,.38,3,r);return c.beginPath(),c.arc(n,e,a*.34,0,2*Math.PI),c.fillStyle=b,c.fill(),g(o)}export function getFont(i,l=500,r="normal"){const o=getComputedStyle(document.body).getPropertyValue(z),c='Oswald, -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',n=o?`${o}, ${c}`:c;return`${r} ${l} ${i}px ${n}`}
@@ -1 +1 @@
1
- import{getConfig as x}from"@expofp/config";import{degToRad as O,Rect as T}from"@expofp/geometry";import{resolve as v}from"@expofp/resolve";import{BOOTHS_PAINTER_MARKER as D,SEPARATOR as m}from"../../../../constants";import{getFpPaths as H}from"../../../../data/fp-payloads";import{createImageDef as k,createLayerDef as F}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 R,FG_LAYER_NAME as $}from"./config-bg";import q,{BOOTHS_CHUNK_SIZE as z}from"./config-booths";import{getImageLayerName as Q,getLayerIcons as V}from"./loadBoothsImages";function W(e){return e.childLayers.length?e.childLayers:Y(e,e.basePriority,15).layers}function E(e,t,f){return new Promise(async g=>{let n=[];const i=K(c,t),s=await Z(t),a=[],h=J(i,z),l=G.booths.filter(o=>o.rect&&(!o.layer||o.layer===t||o.layer.childLayers.includes(t))&&o.exhibitors.find(r=>!!r.logoInBooth&&!!r.logo?.url)&&!c.uiState.hideLogoInBooth),I=new Map(l.map(o=>[o.id,o.noLabels]));l.forEach(o=>o.noLabels=!0),i.length&&h.forEach((o,r)=>{a.push(q(e,`${t.name}${m}${D}${m}${r}`,o))}),l.forEach(o=>{o.noLabels=I.get(o.id)}),t.loaded=!0;const y=s.children.find(o=>o.name===R),u=s.children.find(o=>o.name===$),p=Q(t.name),d=V(t),L={name:p,children:[]};d.length&&e.onLayerImages(p,async()=>{const o=await U(d),r=[];for(const w of o.filter(Boolean)){const{bounds:{x:b,y:P,height:A,angle:S,width:_},htmlImage:M}=w,N=T.fromMinMax({x:b,y:P},{x:b+_,y:P+A},O(S)),C=k(M,N);r.push({shape:C})}return{layer:L,children:r}}),y&&n.push({...y,name:`${s.name}${m}${R}`}),a.length&&n.push(...a),u&&n.push({...u,name:`${s.name}${m}${$}`}),d.length&&n.push(L);const B=t.childLayers.sort((o,r)=>o.basePriority-r.basePriority).map(async o=>E(e,o,!0));Promise.all(B).then(o=>{const r=o.flat();r.length&&n.push(...r),t.children=n,t.configured=!0,g(F(t.name,n,{hidden:!f}))})})}export default async function X(e,t){return e.configured?Promise.resolve({name:e.name,children:e.children}):new Promise(async(f,g)=>{if(c.layerStore.mode!==j.Default&&!H(e.name)&&!e.rootParent)try{const a=x().fpSvgLayerJsRefs[e.name];a&&await v(a)}catch(a){console.warn(`Layer data not loaded: ${e.name}`,a)}const n=W(e);n.length&&(e.childLayers=n);const{layers:i}=c.layerStore;c.layerStore.layers=[...i,...n.filter(a=>!i.some(h=>h.name===a.name))];const s=await E(t,e,e.visible);f(s)})}
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)})}
@@ -0,0 +1,31 @@
1
+ import { type Booth } from '../../../../store/BoothStore';
2
+ import { type Layer } from '../../../../store/LayerStore';
3
+ /**
4
+ * Whether outdoor PoI markers are switched on for this load. Gated behind
5
+ * `enableExperimentalOutdoorMarkers` (unset or `false` = off), which is the one
6
+ * check both halves of the feature share: layer containment here and marker
7
+ * rendering in `usePoiMarkers`.
8
+ */
9
+ export declare function isOutdoorMarkersEnabled(): boolean;
10
+ /**
11
+ * Whether a designer layer is an Outdoor PoI layer. Name-only: the feature flag
12
+ * is checked by {@link configOutdoorPoiLayer}, so this stays a pure predicate.
13
+ */
14
+ export declare function isOutdoorPoiLayer(l: Layer): boolean;
15
+ /**
16
+ * Handles the Outdoor PoI markers (hotels, parking, transit) for one designer
17
+ * layer. Outdoor layers contain nothing but PoI pins — points without a
18
+ * physical size — so the layer contributes nothing to the renderer scene. In
19
+ * the geo map every PoI booth becomes a fixed-size native MapLibre marker
20
+ * (usePoiMarkers); in floorplan-only and legacy-SVG modes nothing renders.
21
+ * Clicks, selection and routing are unaffected — booths are hit-tested by
22
+ * geometry (getBoothIdFromClientXy), not by the rendered shape. Rationale:
23
+ * docs/adr/0002-outdoor-poi-layer-containment.md.
24
+ *
25
+ * Returns true when the layer is an Outdoor layer; the caller must then
26
+ * exclude it from the scene. False leaves regular layers exactly as-is —
27
+ * including with `enableExperimentalOutdoorMarkers` off, so Outdoor layers then
28
+ * draw the way they did before the feature existed.
29
+ */
30
+ export declare function configOutdoorPoiLayer(l: Layer, booths: readonly Booth[]): boolean;
31
+ //# sourceMappingURL=config-outdoor-poi.d.ts.map
@@ -0,0 +1 @@
1
+ import m from"color";import{OUTDOOR_LAYER_PREFIX as u,POI_MARKER_PIN_WIDTH_PX as P,POI_PIN_DEFAULT_COLOR as y}from"../../../../constants";import I from"../../../../data";import s,{uiState as g}from"../../../../store";import{loadImage as M}from"../../../../utils/loadImage";import{createPoiPinImage as w}from"./canvases";const d=r=>!!r&&r!=="transparent"&&r!=="none";function O(r){const i=(r.paths??[]).map(a=>a.color).find(d),t=(r.shapes??[]).map(a=>a.color).find(d),n=i??t??null;if(!n)return null;try{return g.monochrome?m(n).grayscale().rgb().string():n}catch{return n}}export function isOutdoorMarkersEnabled(){return I.enableExperimentalOutdoorMarkers===!0}export function isOutdoorPoiLayer(r){return r.name.toLowerCase().startsWith(u.toLowerCase())}async function T(r){const i=s.poiMarkerStore.generation,t=window.devicePixelRatio||1,n=[],a=new Map((s.poiTypeStore?.poiTypes??[]).map(e=>[e.id,e])),c=new Map,f=e=>{let o=c.get(e);return o||(o=M(e),c.set(e,o)),o};await Promise.all(r.map(async e=>{const o=e.poiTypeId==null?void 0:a.get(e.poiTypeId)?.iconUrl,p=o?await f(o):null;o&&!p&&console.warn("PoI icon failed to load",e.name,o);const l=e.rect.center;n.push({boothId:e.id,center:{x:l.x,y:l.y},icon:w(p,P,t,O(e)??y)})})),s.poiMarkerStore.generation===i&&s.poiMarkerStore.addMany(n)}export function configOutdoorPoiLayer(r,i){return!isOutdoorMarkersEnabled()||!isOutdoorPoiLayer(r)?!1:(s.maplibreStore.showMaplibre&&T(i.filter(t=>t.poiTypeId&&t.rect)),!0)}
@@ -1 +1 @@
1
- import{jsx as Z}from"react/jsx-runtime";import{degToRad as z}from"@expofp/geometry";import H from"color";import{runInAction as Q}from"mobx";import{observer as Y}from"mobx-react-lite";import{useCallback as F,useEffect as $,useMemo as p,useRef as m,useState as B}from"react";import q from"../../data";import{getLayerSvg as ee,svgArea as x,svgAreaExplicit as re}from"../../data/svg";import{createSceneDef as te}from"../../renderer";import a,{uiState as y}from"../../store";import D from"../../tools/settings";import{resolveVenueFitRect as oe}from"../../utils/scene-bounds";import ne from"../Map/drawing/config/config-all";import{loadLayersImages as ae}from"../Map/drawing/config/loadBoothsImages";import{useBuildRoute as ie}from"../Map/traffic/useBuildRoute";import{useManageTraffic as ce}from"../Map/traffic/useManageTraffic";import se from"./MaplibreWrapper";import{useCameraReactions as le}from"./useCameraReactions";import{useDimming as ue}from"./useDimming";import{useKioskIdleEvents as fe}from"./useKioskIdleEvents";import{useLayerVisibilitySync as me}from"./useLayerVisibilitySync";import{useRendererEvents as pe}from"./useRendererEvents";import{useWayfindingAndMarkers as de}from"./useWayfindingAndMarkers";import{deriveGeoConfig as ge,getLocalRectGeoBounds as Re,getVisibleRectFitPadding as be,INITIAL_FIT_ZOOM_ADJUSTMENT as ye}from"./utils/geo-config";import{applyMapOptions as j,DEFAULT_MAP_OPTIONS as Se,getTileSource as he,MAP_2D_OPTIONS as Ae}from"./utils/map-helpers";import{calculateTransformMatrix as Ce}from"./utils/solver";const w="routes-api.expofp.com",Me=800;function De(e,s,n){return{getCameraState:()=>{const t=e.getCenter();return{lng:t.lng,lat:t.lat,zoom:e.getZoom(),bearing:e.getBearing(),pitch:e.getPitch()}},applyCameraState:t=>{e.easeTo({center:[t.lng,t.lat],zoom:t.zoom,bearing:t.bearing??s,pitch:t.pitch??n(),duration:Me,essential:!0})},resetPitch:()=>{const t=n();e.getPitch()!==t&&e.jumpTo({pitch:t})}}}function N(){Q(()=>{a.layerStore.layers.forEach(e=>{e.configured=!1,e.children=[],e.loaded=!1}),a.layerStore.layersLoaded=!1})}function U(e,s){const n=[];for(const t of e.rollRegistry.invoke(s))Array.isArray(t)?n.push(...t):n.push(t);n.length&&e.update(...n)}function ve(e){const s=Math.abs(e[0]??0),n=Math.hypot(e[0]??0,e[1]??0);return s<=0||n<=0?1:s/n}const Te=Y(function({viewMode:s}){const[n,t]=B(null),[v,_]=B(null),o=a.rendererService,T=m(null),u=m(null),S=m(null),P=m(null),I=m(null),h=m(null),r=p(()=>ge(),[]),k=p(()=>{const{rect:c}=oe({layerViewbox:a.layerStore.viewboxRectangle,explicitArea:re?x:null,layerRectangle:a.layerStore.rectangle,sceneDef:n,svgArea:x});return c},[n]),d=p(()=>r?{center:r.center,bearing:r.bearing,zoom:r.zoom,bounds:Re(k,r.gpsConfig),fitPadding:be(0),zoomAdjustment:ye}:null,[r,k]),g=p(()=>r?Ce(r.gpsConfig,ee()?.getAttribute("units")):null,[r]),R=p(()=>({...s==="map2d"?Ae:Se}),[s]),E=m(R),V=p(()=>he(),[]),{mapDimAnimatorRef:A,venueDimAnimatorRef:C,handleMapDimLayerReady:G}=ue(u,o);$(()=>{if(!r)return;let c=!1;N();const i=ne(o).then(({layers:l,cleanup:f})=>{if(c){f();return}P.current=f;const M=H(D.backgroundColor==="none"?"#ebebeb":D.backgroundColor).string(),O=te(l,x,M);t(O)}).catch(l=>{c||console.warn("Maplibre scene configuration failed.",l)}),L=A.current,b=C.current;return()=>{c=!0,N();const l=T.current;i.finally(()=>o.disposeIfCurrent(l)),S.current?.(),S.current=null,P.current?.(),P.current=null,h.current&&(a.maplibreStore.clearCameraPortIfCurrent(h.current),h.current=null),T.current=null,u.current=null,I.current=null,_(null),L?.stop(),b?.stop(),y.sceneDefReady=!1}},[r,A,o,C]);const X=F((c,i,L,b)=>{T.current=c,u.current=i,I.current=b,_(c),o.attach(c,L,b,g?ve(g):1),j(i,E.current);const l=De(i,r?.bearing??i.getBearing(),()=>E.current.pitch??0);h.current=l,a.maplibreStore.setCameraPort(l),A.current?.setTarget(y.dimmed,{immediate:!0}),C.current?.setTarget(y.dimmed,{immediate:!0}),S.current?.();const f=()=>{const O=i.getBearing()-(r?.bearing??0);U(o,z(O))};i.on("rotate",f),i.on("rotateend",f),S.current=()=>{i.off("rotate",f),i.off("rotateend",f)},ae(o);const M=o.ptScaleRegistry.invoke(o.scale||1);M.length&&o.update(...M),U(o,z(i.getBearing()-(r?.bearing??0))),a.layerStore.layersLoaded=!0,a.fp.onFpConfigured&&a.fp.onFpConfigured(),y.sceneDefReady=!0,b()},[o,A,g,C,r]);$(()=>{E.current=R,j(u.current,R,!0)},[R]),pe(v,o),fe(v,u),de(v,o),me(o,u,r),le(u,r,n),ie({enabled:a.layerStore.layersLoaded&&y.buildRoute,rendererService:o});const J=q.busRoutes??!1;ce({permission:a.layerStore.layersLoaded&&J,rendererService:o,dataJsonUrl:`https://${w}/v1/routes?expo=${D.EXPO}`,websocketUrl:`wss://${w}/locations?expo=${D.EXPO}`});const K=F(c=>{console.warn("Maplibre map failed to load; falling back to floorplan mode.",c),a.maplibreStore.deactivateMaplibre()},[]);if(!r||!d||!g||!n)return null;const W=`${d.center.join(",")}:${d.bearing}:${d.zoom}`;return Z(se,{sceneDef:n,geoConfig:d,staticTransform:g,tileSource:V,mapOptions:R,onRendererReady:X,onMapDimLayerReady:G,onMapLoadError:K},W)});export default Te;
1
+ import{jsx as H}from"react/jsx-runtime";import{degToRad as F}from"@expofp/geometry";import Q from"color";import{runInAction as Y}from"mobx";import{observer as q}from"mobx-react-lite";import{useCallback as $,useEffect as B,useMemo as p,useRef as m,useState as j}from"react";import ee from"../../data";import{getLayerSvg as re,svgArea as E,svgAreaExplicit as te}from"../../data/svg";import{createSceneDef as oe}from"../../renderer";import a,{uiState as L}from"../../store";import A from"../../tools/settings";import{resolveVenueFitRect as ne}from"../../utils/scene-bounds";import ae from"../Map/drawing/config/config-all";import{loadLayersImages as ie}from"../Map/drawing/config/loadBoothsImages";import{useBuildRoute as ce}from"../Map/traffic/useBuildRoute";import{useManageTraffic as le}from"../Map/traffic/useManageTraffic";import se from"./MaplibreWrapper";import{useCameraReactions as ue}from"./useCameraReactions";import{useDimming as fe}from"./useDimming";import{useKioskIdleEvents as me}from"./useKioskIdleEvents";import{useLayerVisibilitySync as pe}from"./useLayerVisibilitySync";import{usePoiMarkers as de}from"./usePoiMarkers";import{useRendererEvents as ge}from"./useRendererEvents";import{useWayfindingAndMarkers as Re}from"./useWayfindingAndMarkers";import{deriveGeoConfig as be,getLocalRectGeoBounds as ye,getVisibleRectFitPadding as Se,INITIAL_FIT_ZOOM_ADJUSTMENT as Me}from"./utils/geo-config";import{applyMapOptions as w,DEFAULT_MAP_OPTIONS as he,getTileSource as Ae,MAP_2D_OPTIONS as Ce}from"./utils/map-helpers";import{calculateTransformMatrix as De}from"./utils/solver";const N="routes-api.expofp.com",ve=800;function Pe(e,l,n){return{getCameraState:()=>{const t=e.getCenter();return{lng:t.lng,lat:t.lat,zoom:e.getZoom(),bearing:e.getBearing(),pitch:e.getPitch()}},applyCameraState:t=>{e.easeTo({center:[t.lng,t.lat],zoom:t.zoom,bearing:t.bearing??l,pitch:t.pitch??n(),duration:ve,essential:!0})},resetPitch:()=>{const t=n();e.getPitch()!==t&&e.jumpTo({pitch:t})}}}function U(){a.poiMarkerStore.clear(),Y(()=>{a.layerStore.layers.forEach(e=>{e.configured=!1,e.children=[],e.loaded=!1}),a.layerStore.layersLoaded=!1})}function V(e,l){const n=[];for(const t of e.rollRegistry.invoke(l))Array.isArray(t)?n.push(...t):n.push(t);n.length&&e.update(...n)}function Te(e){const l=Math.abs(e[0]??0),n=Math.hypot(e[0]??0,e[1]??0);return l<=0||n<=0?1:l/n}const Ee=q(function({viewMode:l}){const[n,t]=j(null),[y,O]=j(null),o=a.rendererService,C=m(null),s=m(null),S=m(null),D=m(null),x=m(null),M=m(null),r=p(()=>be(),[]),_=p(()=>{const{rect:c}=ne({layerViewbox:a.layerStore.viewboxRectangle,explicitArea:te?E:null,layerRectangle:a.layerStore.rectangle,sceneDef:n,svgArea:E});return c},[n]),d=p(()=>r?{center:r.center,bearing:r.bearing,zoom:r.zoom,bounds:ye(_,r.gpsConfig),fitPadding:Se(0),zoomAdjustment:Me}:null,[r,_]),g=p(()=>r?De(r.gpsConfig,re()?.getAttribute("units")):null,[r]),R=p(()=>({...l==="map2d"?Ce:he}),[l]),v=m(R),G=p(()=>Ae(),[]),{mapDimAnimatorRef:k,venueDimAnimatorRef:I,applyDimmingTarget:z,handleMapDimLayerReady:X}=fe(s,o);B(()=>{if(!r)return;let c=!1;U();const i=ae(o).then(({layers:u,cleanup:f})=>{if(c){f();return}D.current=f;const h=Q(A.backgroundColor==="none"?"#ebebeb":A.backgroundColor).string(),T=oe(u,E,h);t(T)}).catch(u=>{c||console.warn("Maplibre scene configuration failed.",u)}),P=k.current,b=I.current;return()=>{c=!0,U();const u=C.current;i.finally(()=>o.disposeIfCurrent(u)),S.current?.(),S.current=null,D.current?.(),D.current=null,M.current&&(a.maplibreStore.clearCameraPortIfCurrent(M.current),M.current=null),C.current=null,s.current=null,x.current=null,O(null),P?.stop(),b?.stop(),L.sceneDefReady=!1}},[r,k,o,I]);const J=$((c,i,P,b)=>{C.current=c,s.current=i,x.current=b,O(c),o.attach(c,P,b,g?Te(g):1),w(i,v.current);const u=Pe(i,r?.bearing??i.getBearing(),()=>v.current.pitch??0);M.current=u,a.maplibreStore.setCameraPort(u),z({immediate:!0}),S.current?.();const f=()=>{const T=i.getBearing()-(r?.bearing??0);V(o,F(T))};i.on("rotate",f),i.on("rotateend",f),S.current=()=>{i.off("rotate",f),i.off("rotateend",f)},ie(o);const h=o.ptScaleRegistry.invoke(o.scale||1);h.length&&o.update(...h),V(o,F(i.getBearing()-(r?.bearing??0))),a.layerStore.layersLoaded=!0,a.fp.onFpConfigured&&a.fp.onFpConfigured(),L.sceneDefReady=!0,b()},[o,z,g,r]);B(()=>{v.current=R,w(s.current,R,!0)},[R]),ge(y,o),me(y,s),Re(y,o),de(y,s,r),pe(o,s,r),ue(s,r,n),ce({enabled:a.layerStore.layersLoaded&&L.buildRoute,rendererService:o});const K=ee.busRoutes??!1;le({permission:a.layerStore.layersLoaded&&K,rendererService:o,dataJsonUrl:`https://${N}/v1/routes?expo=${A.EXPO}`,websocketUrl:`wss://${N}/locations?expo=${A.EXPO}`});const W=$(c=>{console.warn("Maplibre map failed to load; falling back to floorplan mode.",c),a.maplibreStore.deactivateMaplibre()},[]);if(!r||!d||!g||!n)return null;const Z=`${d.center.join(",")}:${d.bearing}:${d.zoom}`;return H(se,{sceneDef:n,geoConfig:d,staticTransform:g,tileSource:G,mapOptions:R,onRendererReady:J,onMapDimLayerReady:X,onMapLoadError:W},Z)});export default Ee;
@@ -1 +1 @@
1
- import{Box as b}from"@expofp/geometry";import{svgArea as l,svgAreaExplicit as x}from"../../data/svg";import p,{uiState as a}from"../../store";import{convertLocalToGps as h}from"../../utils/gps";import{useReaction as m}from"../../utils/mobx";import{expandRectByPercent as T,getVenueFitMarginPercent as S,resolveVenueFitRect as L}from"../../utils/scene-bounds";import{fitMapToLocalRect as f}from"./utils/geo-config";const s=a;function d(r){return T(r,S(r,l))}export function useCameraReactions(r,o,y){m(()=>s.moveToBooths,e=>{const t=r.current;if(!e||!t||!o)return;const n=e.filter(c=>c.rect);if(n.length===0)return;const i=b.fromUnion(...n.map(c=>c.rect));f(t,d(i),o),s.moveToBooths=null}),m(()=>s.moveToRect,e=>{const t=r.current;!e||!t||!o||(f(t,e,o),s.moveToRect=null)}),m(()=>s.zoomBy,e=>{const t=r.current;!e||!t||(t.flyTo({zoom:t.getZoom()+(e>1?.5:-.5),animate:!0,duration:500}),s.zoomBy=null)}),m(()=>a.moveToLocation,e=>{const t=r.current,n=p.routeStore.currentPosition;if(!e||!t||!n)return;const{lng:i,lat:c}=n,v=typeof i=="number"&&Number.isFinite(i)&&typeof c=="number"&&Number.isFinite(c);let u;if(v)u=[i,c];else{if(!o)return;u=h(n.x,n.y,o.gpsConfig)}t.flyTo({center:u,animate:!0,duration:1e3}),t.once("moveend",()=>{a.moveToLocation=!1})}),m(()=>a.centerMap,e=>{const t=r.current;if(!e||!t||!o)return;if(!(a.list.type==="search"&&!a.list.text)){const{rect:i}=L({layerViewbox:p.layerStore.viewboxRectangle,explicitArea:x?l:null,layerRectangle:p.layerStore.rectangle,sceneDef:y,svgArea:l});f(t,i,o)}a.centerMap=!1})}
1
+ import{Box as b}from"@expofp/geometry";import{svgArea as f,svgAreaExplicit as T}from"../../data/svg";import m,{uiState as a}from"../../store";import{convertLocalToGps as h}from"../../utils/gps";import{useReaction as u}from"../../utils/mobx";import{expandRectByPercent as v,getVenueFitMarginPercent as x,resolveVenueFitRect as M}from"../../utils/scene-bounds";import{fitMapToLocalRect as d,getVisibleRectFitPadding as O,isLngLatInVisibleViewport as S}from"./utils/geo-config";const s=a,L=15,P=24;function B(e){return v(e,x(e,f))}function I(e,r){return Math.min(Math.max(r,e.getMinZoom()),e.getMaxZoom())}function R(e,r,l){if(l.length!==1)return!1;const o=l[0]?.id,t=m.poiMarkerStore.markers.find(c=>c.boothId===o);if(!t)return!1;const n=h(t.center.x,t.center.y,r.gpsConfig),i=O(P);return S(e,n,i)||e.easeTo({center:n,zoom:I(e,L),bearing:r.bearing,duration:500,essential:!0}),!0}export function useCameraReactions(e,r,l){u(()=>s.moveToBooths,o=>{const t=e.current;if(!o||!t||!r)return;const n=o.filter(c=>c.rect);if(n.length===0)return;if(R(t,r,n)){s.moveToBooths=null;return}const i=b.fromUnion(...n.map(c=>c.rect));d(t,B(i),r),s.moveToBooths=null}),u(()=>s.moveToRect,o=>{const t=e.current;!o||!t||!r||(d(t,o,r),s.moveToRect=null)}),u(()=>s.zoomBy,o=>{const t=e.current;!o||!t||(t.flyTo({zoom:t.getZoom()+(o>1?.5:-.5),animate:!0,duration:500}),s.zoomBy=null)}),u(()=>a.moveToLocation,o=>{const t=e.current,n=m.routeStore.currentPosition;if(!o||!t||!n)return;const{lng:i,lat:c}=n,y=typeof i=="number"&&Number.isFinite(i)&&typeof c=="number"&&Number.isFinite(c);let p;if(y)p=[i,c];else{if(!r)return;p=h(n.x,n.y,r.gpsConfig)}t.flyTo({center:p,animate:!0,duration:1e3}),t.once("moveend",()=>{a.moveToLocation=!1})}),u(()=>a.centerMap,o=>{const t=e.current;if(!o||!t||!r)return;if(!(a.list.type==="search"&&!a.list.text)){const{rect:i}=M({layerViewbox:m.layerStore.viewboxRectangle,explicitArea:T?f:null,layerRectangle:m.layerStore.rectangle,sceneDef:l,svgArea:f});d(t,i,r)}a.centerMap=!1})}
@@ -5,8 +5,17 @@ import { type DimmingAnimator } from '../../utils/dimming';
5
5
  export interface DimmingControls {
6
6
  mapDimAnimatorRef: RefObject<DimmingAnimator | null>;
7
7
  venueDimAnimatorRef: RefObject<DimmingAnimator | null>;
8
+ applyDimmingTarget: (options?: {
9
+ immediate?: boolean;
10
+ }) => void;
8
11
  handleMapDimLayerReady: (map: MaplibreMap) => void;
9
12
  }
13
+ /**
14
+ * The map-wide dim target: `uiState.dimmed`, except while outdoor PoI markers
15
+ * suppress it. Single source of truth — the marker layers dim themselves
16
+ * (usePoiMarkers) and must agree with the plan and basemap.
17
+ */
18
+ export declare function getMapDimTarget(): boolean;
10
19
  /**
11
20
  * Manages scene dimming: creates map and venue dim animators,
12
21
  * keeps them in sync with uiState.dimmed via a MobX reaction,
@@ -1 +1 @@
1
- import{useCallback as I,useEffect as c,useRef as o}from"react";import{uiState as l}from"../../store";import{applyVenueDimValue as T,createDimmingAnimator as s,DIM_INTENSITY as p,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 useDimming(i,u){const a=o(u);c(()=>{a.current=u},[u]);const e=o(null),r=o(null);c(()=>{const t=s(m=>{f(i.current,m*p)}),n=s(m=>{T(a.current,m*V)});return e.current=t,r.current=n,()=>{t.stop(),n.stop(),e.current=null,r.current=null}},[i]),d(()=>l.dimmed,t=>{e.current?.setTarget(t),r.current?.setTarget(t)});const D=I(t=>{const n=e.current?.getValue()??(l.dimmed?1:0);f(t,n*p)},[]);return{mapDimAnimatorRef:e,venueDimAnimatorRef:r,handleMapDimLayerReady:D}}
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}}
@@ -0,0 +1,26 @@
1
+ import { type Renderer } from '@expofp/renderer';
2
+ import { type Map as MaplibreMap } from 'maplibre-gl';
3
+ import { type RefObject } from 'react';
4
+ import { type GeoConfig } from './utils/geo-config';
5
+ /**
6
+ * Renders the outdoor PoI markers (hotels, parking, transit) as native
7
+ * MapLibre layers: a GeoJSON source with `cluster: true` plus symbol/circle
8
+ * layers on top of it. Geo map only — the hook is mounted from
9
+ * MaplibreAdapter, and runs once the renderer's `3d` custom layer exists so
10
+ * the marker stack draws above the floor plan.
11
+ *
12
+ * The marker feed is `store.poiMarkerStore`: `config-outdoor-poi` builds the
13
+ * marker records (including the rasterized pins, registered here via
14
+ * `map.addImage`), and the store derives selection (`selectedMarkerId`), the
15
+ * active filter (`outdoorFilter`) and dimming suppression from them. These
16
+ * layers are the *only* rendering outdoor PoIs get — see
17
+ * `configOutdoorPoiLayer`. Clicks are claimed from the renderer path via
18
+ * `poiMarkerHitTest`.
19
+ *
20
+ * Gated behind `enableExperimentalOutdoorMarkers`: with the flag off no layers,
21
+ * images or handlers are created at all. The feed is empty in that case too
22
+ * (`configOutdoorPoiLayer` never publishes), so this is belt-and-braces — it
23
+ * keeps the map untouched even if markers reach the store another way.
24
+ */
25
+ export declare function usePoiMarkers(renderer: Renderer | null, mapRef: RefObject<MaplibreMap | null>, geoConfig: GeoConfig | null): void;
26
+ //# sourceMappingURL=usePoiMarkers.d.ts.map
@@ -0,0 +1 @@
1
+ import{Box as j}from"@expofp/geometry";import{reaction as h}from"mobx";import{useEffect as K}from"react";import{POI_CLUSTER_COLOR as W,POI_CLUSTER_MIN_POINTS as q,POI_CLUSTER_RADIUS_PX as $,POI_CLUSTER_SIZE_PX as J,POI_CLUSTER_STROKE_COLOR as Q,POI_CLUSTER_STROKE_WIDTH_PX as ee,POI_CLUSTER_TEXT_SIZE_PX as te,POI_SELECTED_PIN_WIDTH_PX as oe}from"../../constants";import c from"../../store";import re from"../../tools/settings";import{DIM_INTENSITY as ie}from"../../utils/dimming";import{convertLocalToGps as C}from"../../utils/gps";import{createPoiPinheadImage as ne}from"../Map/drawing/config/canvases";import{isOutdoorMarkersEnabled as ce}from"../Map/drawing/config/config-outdoor-poi";import{getMapDimTarget as v}from"./useDimming";import{getLocalRectGeoBounds as se,getVisibleRectFitPadding as ae,isLngLatInVisibleViewport as le}from"./utils/geo-config";import{poiMarkerHitTest as U}from"./utils/poi-marker-hit-test";const s="expofp-poi",a="expofp-poi-clusters",S="expofp-poi-cluster-count",I="expofp-poi-unclustered",y="expofp-poi-selected",P="expofp-poi-pinhead-image",A=[a,S,I,y],pe=A.filter(p=>p!==S),L=p=>`expofp-poi-icon-${p}`;export function usePoiMarkers(p,E,f){K(()=>{if(!ce())return;const e=E.current;if(!p||!e||!f)return;const{gpsConfig:b}=f,l=new Set,k=window.devicePixelRatio||1,w=re.colors?.booths?.selected||"#3b6ef5",F=ne(oe,k,w),T=t=>C(t.center.x,t.center.y,b),O=(t,o)=>{e.hasImage(t)&&e.removeImage(t),e.addImage(t,o,{pixelRatio:k}),l.add(t)},N=t=>{const o=c.poiMarkerStore.markers,i=new Set(o.map(r=>L(r.boothId)));i.add(P);for(const r of[...l])i.has(r)||(e.hasImage(r)&&e.removeImage(r),l.delete(r));for(const r of o){const n=L(r.boothId);(t||!l.has(n))&&O(n,r.icon)}l.has(P)||O(P,F)},B=()=>{const t=c.poiMarkerStore.selectedMarkerId,o=c.poiMarkerStore.outdoorFilter,i=!o.active;let r=c.poiMarkerStore.markers;return t!==null?r=r.filter(n=>n.boothId===t):o.active&&(r=o.matchingMarkers),{cluster:i,data:{type:"FeatureCollection",features:r.map(n=>({type:"Feature",geometry:{type:"Point",coordinates:T(n)},properties:{boothId:n.boothId,icon:L(n.boothId),pinhead:n.boothId===t}}))}}},Y=()=>{let t=null;for(const o of e.getStyle()?.layers??[]){if(o.type!=="symbol")continue;const i=o.layout?.["text-font"];if(!(!Array.isArray(i)||!i.every(r=>typeof r=="string"))){if(!i.some(r=>/italic/i.test(r)))return i;t??=i}}return t??["Noto Sans Regular"]};let g=null;const R=()=>{for(const t of A)e.getLayer(t)&&e.removeLayer(t);e.getSource(s)&&e.removeSource(s),g=null},X=(t,o)=>{if(g!==null&&g!==o&&R(),e.getSource(s)||(e.addSource(s,{type:"geojson",data:t,cluster:o,clusterRadius:$,clusterMinPoints:q}),g=o),e.getLayer(a))return;const i=["!",["has","point_count"]],r=["==",["coalesce",["get","pinhead"],!1],!0];e.addLayer({id:a,type:"circle",source:s,filter:["has","point_count"],paint:{"circle-radius":J/2,"circle-color":W,"circle-stroke-color":Q,"circle-stroke-width":ee,"circle-pitch-alignment":"viewport"}}),e.addLayer({id:S,type:"symbol",source:s,filter:["has","point_count"],layout:{"text-field":["get","point_count_abbreviated"],"text-font":Y(),"text-size":te,"text-allow-overlap":!0,"text-ignore-placement":!0},paint:{"text-color":"#ffffff"}}),e.addLayer({id:I,type:"symbol",source:s,filter:["all",i,["!",r]],layout:{"icon-image":["get","icon"],"icon-anchor":"bottom","icon-allow-overlap":!0,"icon-ignore-placement":!0}}),e.addLayer({id:y,type:"symbol",source:s,filter:["all",i,r],layout:{"icon-image":P,"icon-anchor":"bottom","icon-allow-overlap":!0,"icon-ignore-placement":!0}})},M=()=>{if(!e.getLayer(a))return;const t=v()?1-ie:1;e.setPaintProperty(a,"circle-opacity",t),e.setPaintProperty(a,"circle-stroke-opacity",t),e.setPaintProperty(S,"text-opacity",t),e.setPaintProperty(I,"icon-opacity",t),e.setPaintProperty(y,"icon-opacity",t)},d=(t=!1)=>{N(t);const{cluster:o,data:i}=B();X(i,o),e.getSource(s)?.setData(i),M()},z=t=>{if(!t.length)return;const o=ae(50);if(t.every(m=>le(e,T(m),o)))return;const r=j.fromPoints(t.map(m=>m.center)),n=se(r,b),u=e.cameraForBounds(n,{padding:o,bearing:f.bearing});!u?.center||typeof u.zoom!="number"||e.easeTo({center:u.center,zoom:Math.min(e.getZoom(),u.zoom),bearing:f.bearing,duration:500,essential:!0})},_=t=>{const o=t.features?.[0]?.properties?.boothId;if(typeof o!="number")return;const i=c.boothStore.boothById.get(o);i&&c.clickBooth(i)},x=t=>{const o=t.features?.[0],i=o?.properties?.cluster_id,r=e.getSource(s);if(typeof i!="number"||!r||o?.geometry?.type!=="Point")return;const[n=0,u=0]=o.geometry.coordinates;r.getClusterExpansionZoom(i).then(m=>{e.easeTo({center:[n,u],zoom:Math.min(m,e.getMaxZoom()),duration:500})})};e.on("click",I,_),e.on("click",y,_),e.on("click",a,x),U.set((t,o)=>{const i=pe.filter(n=>!!e.getLayer(n));if(!i.length)return!1;const r=e.project(C(t,o,b));return e.queryRenderedFeatures([r.x,r.y],{layers:i}).length>0});const D=()=>{l.clear(),d(!0)};e.on("style.load",D);const H=h(()=>c.poiMarkerStore.markers,()=>d(!0)),V=h(()=>c.poiMarkerStore.selectedMarkerId,()=>d()),Z=h(()=>c.poiMarkerStore.outdoorFilter.key,()=>{d(),z(c.poiMarkerStore.outdoorFilter.matchingMarkers)}),G=h(()=>v(),()=>M());return d(!0),()=>{H(),V(),Z(),G(),U.set(null),e.off("style.load",D),e.off("click",I,_),e.off("click",y,_),e.off("click",a,x);try{R();for(const t of l)e.hasImage(t)&&e.removeImage(t)}catch{}}},[p,E,f])}
@@ -1 +1 @@
1
- import{useEffect as g}from"react";import{pickDefaultScene as h}from"../../renderer/engine-core/defs";import c,{uiState as o}from"../../store";import{LayerMode as p}from"../../store/LayerStore";import k from"../Map/booth-by-xy";import{getMarkerFromClick as L}from"../Map/drawing/config/config-markers";import{getBooth as E}from"./utils/layer-defs";const C=o;export function useRendererEvents(t,m){g(()=>{if(!t)return;const v=({data:s})=>{if(o.setKioskModeEnabled)return;const{point:e,defs:r}=h(s),n=k(e.x,e.y),i=E(r[0]);C.hoveredBooth=n||i||null},d=()=>{o.setKioskModeEnabled||(C.hoveredBooth=null)},f=({data:s})=>{if(!o?.rootElement)return;window.__resett?.(),o.overlayPosition==="bottom"&&o.overlaySize==="full"&&c.showMap();const{point:e,defs:r}=h(s),{x:n,y:i}=e;if(o.onGetCoordsClick){const l=c.layerStore.layers.find(a=>a.visible&&(a.mode===p.TurnedOn||a.mode===p.TurnedOff));o.onGetCoordsClick({x:n,y:i,z:l?.name||null})}if(o.setKioskModeEnabled)return;if(o.onMarkerClick){const l=L(n,i,m.scale);o.onMarkerClick(l)}const y=k(e.x,e.y),b=E(r[0]);c.clickBooth(y||b||null)},u=()=>window.__resett?.();return t.events.addEventListener("pointer:move",v),t.events.addEventListener("pointer:out",d),t.events.addEventListener("pointer:click",f),t.events.addEventListener("navigation:change",u),()=>{t.events.removeEventListener("pointer:move",v),t.events.removeEventListener("pointer:out",d),t.events.removeEventListener("pointer:click",f),t.events.removeEventListener("navigation:change",u)}},[t,m])}
1
+ import{useEffect as g}from"react";import{pickDefaultScene as p}from"../../renderer/engine-core/defs";import c,{uiState as t}from"../../store";import{LayerMode as h}from"../../store/LayerStore";import k from"../Map/booth-by-xy";import{getMarkerFromClick as y}from"../Map/drawing/config/config-markers";import{getBooth as E}from"./utils/layer-defs";import{poiMarkerHitTest as L}from"./utils/poi-marker-hit-test";const C=t;export function useRendererEvents(e,m){g(()=>{if(!e)return;const v=({data:r})=>{if(t.setKioskModeEnabled)return;const{point:o,defs:s}=p(r),n=k(o.x,o.y),i=E(s[0]);C.hoveredBooth=n||i||null},f=()=>{t.setKioskModeEnabled||(C.hoveredBooth=null)},d=({data:r})=>{if(!t?.rootElement)return;window.__resett?.(),t.overlayPosition==="bottom"&&t.overlaySize==="full"&&c.showMap();const{point:o,defs:s}=p(r),{x:n,y:i}=o;if(t.onGetCoordsClick){const l=c.layerStore.layers.find(a=>a.visible&&(a.mode===h.TurnedOn||a.mode===h.TurnedOff));t.onGetCoordsClick({x:n,y:i,z:l?.name||null})}if(t.setKioskModeEnabled||L.test(n,i))return;const M=k(o.x,o.y)||E(s[0]);if(t.onMarkerClick){const l=y(n,i,m.scale);t.onMarkerClick(l)}c.clickBooth(M||null)},u=()=>window.__resett?.();return e.events.addEventListener("pointer:move",v),e.events.addEventListener("pointer:out",f),e.events.addEventListener("pointer:click",d),e.events.addEventListener("navigation:change",u),()=>{e.events.removeEventListener("pointer:move",v),e.events.removeEventListener("pointer:out",f),e.events.removeEventListener("pointer:click",d),e.events.removeEventListener("navigation:change",u)}},[e,m])}
@@ -21,6 +21,8 @@ export declare const INITIAL_FIT_ZOOM_ADJUSTMENT = 0.15;
21
21
  export declare function deriveVenueMapBounds(config: TransformGeoConfig): LngLatBoundsLike | undefined;
22
22
  export declare function getLocalRectGeoBounds(rect: Box, config: TransformGeoConfig): LngLatBoundsLike;
23
23
  export declare function getVisibleRectFitPadding(extraPadding?: number): CameraPaddingOptions;
24
+ /** Whether a lng/lat projects inside the visible viewport, inset by `padding`. */
25
+ export declare function isLngLatInVisibleViewport(map: MaplibreMap, lngLat: [number, number], padding: CameraPaddingOptions): boolean;
24
26
  /** Geographic configuration from fpGeo data; null when unavailable. */
25
27
  export declare function deriveGeoConfig(): GeoConfig | null;
26
28
  export declare function fitMapToLocalRect(map: MaplibreMap | null, rect: Box | null, geoConfig: GeoConfig | null, options?: FitMapOptions): void;
@@ -1 +1 @@
1
- import{LngLatBounds as R}from"maplibre-gl";import{fpGeo as y}from"../../../data/fpGeo";import{svgArea as c}from"../../../data/svg";import{uiState as b}from"../../../store";import{convertLocalToGps as f}from"../../../utils/gps";import{planBearing as z}from"../../../utils/planBearing";export const MAP_BOUNDS_PADDING_FACTOR=3,MAP_BOUNDS_MIN_PADDING_DEGREES=.02,INITIAL_FIT_ZOOM_ADJUSTMENT=.15;const p=1.42,M=.35,D=.9,E=.85,A=8,S=.05;export function deriveVenueMapBounds(t){const n=[[c.min.x,c.min.y],[c.max.x,c.min.y],[c.max.x,c.max.y],[c.min.x,c.max.y]].map(([a,m])=>f(a,m,t));if(!n.every(([a,m])=>Number.isFinite(a)&&Number.isFinite(m)))return;const e=n.map(([a])=>a),o=n.map(([,a])=>a),i=Math.min(...e),r=Math.max(...e),s=Math.min(...o),u=Math.max(...o),x=Math.max((r-i)*MAP_BOUNDS_PADDING_FACTOR,MAP_BOUNDS_MIN_PADDING_DEGREES),h=Math.max((u-s)*MAP_BOUNDS_PADDING_FACTOR,MAP_BOUNDS_MIN_PADDING_DEGREES);return[[i-x,s-h],[r+x,u+h]]}function d(t,n,e,o){const i=Math.min(t.getZoom(),n),r=(e-i)*Math.min(1,o/p);return i+r>=t.getMinZoom()-S}function v(t,n,e){if(d(t,n,e,p))return p;if(!d(t,n,e,M))return null;let o=M,i=p;for(let r=0;r<A;r++){const s=(o+i)/2;d(t,n,e,s)?o=s:i=s}return o}export function getLocalRectGeoBounds(t,n){const e=[f(t.min.x,t.min.y,n),f(t.max.x,t.min.y,n),f(t.max.x,t.max.y,n),f(t.min.x,t.max.y,n)],o=e.map(([r])=>r),i=e.map(([,r])=>r);return[[Math.min(...o),Math.min(...i)],[Math.max(...o),Math.max(...i)]]}export function getVisibleRectFitPadding(t=0){const n=b.canvasVisibleRectPx,e=b.screenSize;return!n||!e?{top:t,bottom:t,left:t,right:t}:{top:Math.max(0,n.min.y)+t,bottom:Math.max(0,e.height-n.max.y)+t,left:Math.max(0,n.min.x)+t,right:Math.max(0,e.width-n.max.x)+t}}export function deriveGeoConfig(){if(!y?.properties?.config)return null;const t=y.properties.config,n=(t.p0.lng+t.p2.lng)/2,e=(t.p0.lat+t.p2.lat)/2,o=z(t.p0,t.p2),i=Number.isFinite(o)?o:t.bearing??0;return{center:[n,e],bearing:i,zoom:16,gpsConfig:t}}export function fitMapToLocalRect(t,n,e,o={}){if(!t||!n||!e||n.size.height===1/0||n.size.width===1/0||n.size.height<=0||n.size.width<=0)return;const i=getLocalRectGeoBounds(n,e.gpsConfig),r=getVisibleRectFitPadding(o.padding??50),s=t.cameraForBounds(i,{padding:r,bearing:e.bearing});if(!s?.center||typeof s.zoom!="number"){t.fitBounds(i,{padding:r,bearing:e.bearing,essential:!0});return}const u=t.project(t.getCenter()),x=t.project(s.center),h=Math.max(t.getCanvas().clientWidth,t.getCanvas().clientHeight,1),a=Math.hypot(x.x-u.x,x.y-u.y)/h,m=Math.abs(t.getZoom()-s.zoom),_=o.duration??Math.min(2800,500+a*450+m*150),l={center:s.center,zoom:s.zoom,bearing:e.bearing,duration:_,essential:!0};if(a<=1.2&&m<=1.5){t.easeTo(l);return}const O=t.getBounds().extend(R.convert(i)),g=t.cameraForBounds(O,{padding:r,bearing:e.bearing});if(!g?.center||typeof g.zoom!="number"||g.zoom>=t.getZoom()-.2){t.easeTo(l);return}const T=v(t,s.zoom,g.zoom);if(T!==null){const F=Math.max(M,T*D),L=Math.round(_*E);t.flyTo({...l,curve:F,duration:L});return}t.easeTo(l)}
1
+ import{LngLatBounds as R}from"maplibre-gl";import{fpGeo as T}from"../../../data/fpGeo";import{svgArea as c}from"../../../data/svg";import{uiState as d}from"../../../store";import{convertLocalToGps as f}from"../../../utils/gps";import{planBearing as v}from"../../../utils/planBearing";export const MAP_BOUNDS_PADDING_FACTOR=3,MAP_BOUNDS_MIN_PADDING_DEGREES=.02,INITIAL_FIT_ZOOM_ADJUSTMENT=.15;const p=1.42,M=.35,z=.9,D=.85,E=8,A=.05;export function deriveVenueMapBounds(t){const n=[[c.min.x,c.min.y],[c.max.x,c.min.y],[c.max.x,c.max.y],[c.min.x,c.max.y]].map(([a,m])=>f(a,m,t));if(!n.every(([a,m])=>Number.isFinite(a)&&Number.isFinite(m)))return;const e=n.map(([a])=>a),o=n.map(([,a])=>a),i=Math.min(...e),r=Math.max(...e),s=Math.min(...o),u=Math.max(...o),x=Math.max((r-i)*MAP_BOUNDS_PADDING_FACTOR,MAP_BOUNDS_MIN_PADDING_DEGREES),h=Math.max((u-s)*MAP_BOUNDS_PADDING_FACTOR,MAP_BOUNDS_MIN_PADDING_DEGREES);return[[i-x,s-h],[r+x,u+h]]}function _(t,n,e,o){const i=Math.min(t.getZoom(),n),r=(e-i)*Math.min(1,o/p);return i+r>=t.getMinZoom()-A}function I(t,n,e){if(_(t,n,e,p))return p;if(!_(t,n,e,M))return null;let o=M,i=p;for(let r=0;r<E;r++){const s=(o+i)/2;_(t,n,e,s)?o=s:i=s}return o}export function getLocalRectGeoBounds(t,n){const e=[f(t.min.x,t.min.y,n),f(t.max.x,t.min.y,n),f(t.max.x,t.max.y,n),f(t.min.x,t.max.y,n)],o=e.map(([r])=>r),i=e.map(([,r])=>r);return[[Math.min(...o),Math.min(...i)],[Math.max(...o),Math.max(...i)]]}export function getVisibleRectFitPadding(t=0){const n=d.canvasVisibleRectPx,e=d.screenSize;return!n||!e?{top:t,bottom:t,left:t,right:t}:{top:Math.max(0,n.min.y)+t,bottom:Math.max(0,e.height-n.max.y)+t,left:Math.max(0,n.min.x)+t,right:Math.max(0,e.width-n.max.x)+t}}export function isLngLatInVisibleViewport(t,n,e){const o=t.project(n),i=t.getCanvas();return o.x>=e.left&&o.x<=i.clientWidth-e.right&&o.y>=e.top&&o.y<=i.clientHeight-e.bottom}export function deriveGeoConfig(){if(!T?.properties?.config)return null;const t=T.properties.config,n=(t.p0.lng+t.p2.lng)/2,e=(t.p0.lat+t.p2.lat)/2,o=v(t.p0,t.p2),i=Number.isFinite(o)?o:t.bearing??0;return{center:[n,e],bearing:i,zoom:16,gpsConfig:t}}export function fitMapToLocalRect(t,n,e,o={}){if(!t||!n||!e||n.size.height===1/0||n.size.width===1/0||n.size.height<=0||n.size.width<=0)return;const i=getLocalRectGeoBounds(n,e.gpsConfig),r=getVisibleRectFitPadding(o.padding??50),s=t.cameraForBounds(i,{padding:r,bearing:e.bearing});if(!s?.center||typeof s.zoom!="number"){t.fitBounds(i,{padding:r,bearing:e.bearing,essential:!0});return}const u=t.project(t.getCenter()),x=t.project(s.center),h=Math.max(t.getCanvas().clientWidth,t.getCanvas().clientHeight,1),a=Math.hypot(x.x-u.x,x.y-u.y)/h,m=Math.abs(t.getZoom()-s.zoom),y=o.duration??Math.min(2800,500+a*450+m*150),l={center:s.center,zoom:s.zoom,bearing:e.bearing,duration:y,essential:!0};if(a<=1.2&&m<=1.5){t.easeTo(l);return}const L=t.getBounds().extend(R.convert(i)),g=t.cameraForBounds(L,{padding:r,bearing:e.bearing});if(!g?.center||typeof g.zoom!="number"||g.zoom>=t.getZoom()-.2){t.easeTo(l);return}const b=I(t,s.zoom,g.zoom);if(b!==null){const O=Math.max(M,b*z),F=Math.round(y*D);t.flyTo({...l,curve:O,duration:F});return}t.easeTo(l)}
@@ -0,0 +1,16 @@
1
+ type PoiMarkerHitTest = (x: number, y: number) => boolean;
2
+ /**
3
+ * Model-space hit-test against the outdoor PoI symbol/cluster layers, set by
4
+ * `usePoiMarkers` while active. The renderer click pipeline
5
+ * (useRendererEvents) consults it so a click handled by a native MapLibre
6
+ * layer does not also select the booth underneath.
7
+ *
8
+ * Deliberately a leaf module (no imports): it decouples the renderer click
9
+ * pipeline from the Maplibre hook that owns the marker layers.
10
+ */
11
+ export declare const poiMarkerHitTest: {
12
+ set(fn: PoiMarkerHitTest | null): void;
13
+ test(x: number, y: number): boolean;
14
+ };
15
+ export {};
16
+ //# sourceMappingURL=poi-marker-hit-test.d.ts.map
@@ -0,0 +1 @@
1
+ let e=null;export const poiMarkerHitTest={set(t){e=t},test(t,s){return e?e(t,s):!1}};
@@ -2,6 +2,17 @@ export declare const VISIBILITY_STORAGE_KEY = "___visibility";
2
2
  export declare const PREVIEW_MODE_ATTRIBUTE = "data-preview-mode";
3
3
  export declare const BOOTHS_PAINTER_MARKER = "booths";
4
4
  export declare const SEPARATOR = ":";
5
+ export declare const OUTDOOR_LAYER_PREFIX = "Outdoor";
6
+ export declare const POI_CLUSTER_RADIUS_PX = 50;
7
+ export declare const POI_CLUSTER_MIN_POINTS = 3;
8
+ export declare const POI_MARKER_PIN_WIDTH_PX = 42;
9
+ export declare const POI_SELECTED_PIN_WIDTH_PX = 36;
10
+ export declare const POI_PIN_DEFAULT_COLOR = "#ea4236";
11
+ export declare const POI_CLUSTER_SIZE_PX = 36;
12
+ export declare const POI_CLUSTER_COLOR = "rgba(234, 66, 54, 0.85)";
13
+ export declare const POI_CLUSTER_STROKE_COLOR = "#ffffff";
14
+ export declare const POI_CLUSTER_STROKE_WIDTH_PX = 2;
15
+ export declare const POI_CLUSTER_TEXT_SIZE_PX = 14;
5
16
  export declare const LAYER_LOGOS_MARKER = "logos";
6
17
  export declare const LAYER_ICONS_MARKER = "icons";
7
18
  export declare const STRING_META_DELIMITER = "$$";
@@ -1 +1 @@
1
- export const VISIBILITY_STORAGE_KEY="___visibility",PREVIEW_MODE_ATTRIBUTE="data-preview-mode",BOOTHS_PAINTER_MARKER="booths",SEPARATOR=":",LAYER_LOGOS_MARKER="logos",LAYER_ICONS_MARKER="icons",STRING_META_DELIMITER="$$",KIOSK_ENABLE_KEY="kiosk",SET_KIOSK_KEY="setkiosk",BOOKMARK_PAINTER_MARKER="booth-bookmark",DEBUG_KEY="debug",DEBUG_STORAGE_KEY="efp-debugMode",DEFAULT_UNITS="ft",PATHWAY_KEY="pathway",CACHE_DURATION=1e3,MOBILE_BREAKPOINT=768,LANGUAGE_TYPE="language",MAX_ROUTE_WAYPOINTS=8,VIEWER_MODE_STORAGE_KEY="efp-viewerMode",LEGACY_VIEWER_MODE_STORAGE_KEY="___viewer_mode",PREVIEW_MODE_STORAGE_KEY="efp-previewMode",LEGACY_PREVIEW_MODE_STORAGE_KEY="___preview_mode",UI_SCALE_STORAGE_KEY="efp-uiScale",LEGACY_UI_SCALE_STORAGE_KEY="___ui-scale",FONT_FACE="--expofp-font-face",FONT_WEIGHT_PRIMARY_BOOTH="--expofp-booth-main-weight",FONT_WEIGHT_SECONDARY_BOOTH="--expofp-booth-details-weight",FONT_WEIGHT_PRIMARY_EXHIBITOR="--expofp-exhibitor-main-weight",FONT_WEIGHT_SECONDARY_EXHIBITOR="--expofp-exhibitor-details-weight",FONT_WEIGHT_PRIMARY_SPECIAL="--expofp-booth-special-weight",ORIENTATION_GRANTED_KEY="efp-compass-permission-granted";
1
+ export const VISIBILITY_STORAGE_KEY="___visibility",PREVIEW_MODE_ATTRIBUTE="data-preview-mode",BOOTHS_PAINTER_MARKER="booths",SEPARATOR=":",OUTDOOR_LAYER_PREFIX="Outdoor",POI_CLUSTER_RADIUS_PX=50,POI_CLUSTER_MIN_POINTS=3,POI_MARKER_PIN_WIDTH_PX=42,POI_SELECTED_PIN_WIDTH_PX=36,POI_PIN_DEFAULT_COLOR="#ea4236",POI_CLUSTER_SIZE_PX=36,POI_CLUSTER_COLOR="rgba(234, 66, 54, 0.85)",POI_CLUSTER_STROKE_COLOR="#ffffff",POI_CLUSTER_STROKE_WIDTH_PX=2,POI_CLUSTER_TEXT_SIZE_PX=14,LAYER_LOGOS_MARKER="logos",LAYER_ICONS_MARKER="icons",STRING_META_DELIMITER="$$",KIOSK_ENABLE_KEY="kiosk",SET_KIOSK_KEY="setkiosk",BOOKMARK_PAINTER_MARKER="booth-bookmark",DEBUG_KEY="debug",DEBUG_STORAGE_KEY="efp-debugMode",DEFAULT_UNITS="ft",PATHWAY_KEY="pathway",CACHE_DURATION=1e3,MOBILE_BREAKPOINT=768,LANGUAGE_TYPE="language",MAX_ROUTE_WAYPOINTS=8,VIEWER_MODE_STORAGE_KEY="efp-viewerMode",LEGACY_VIEWER_MODE_STORAGE_KEY="___viewer_mode",PREVIEW_MODE_STORAGE_KEY="efp-previewMode",LEGACY_PREVIEW_MODE_STORAGE_KEY="___preview_mode",UI_SCALE_STORAGE_KEY="efp-uiScale",LEGACY_UI_SCALE_STORAGE_KEY="___ui-scale",FONT_FACE="--expofp-font-face",FONT_WEIGHT_PRIMARY_BOOTH="--expofp-booth-main-weight",FONT_WEIGHT_SECONDARY_BOOTH="--expofp-booth-details-weight",FONT_WEIGHT_PRIMARY_EXHIBITOR="--expofp-exhibitor-main-weight",FONT_WEIGHT_SECONDARY_EXHIBITOR="--expofp-exhibitor-details-weight",FONT_WEIGHT_PRIMARY_SPECIAL="--expofp-booth-special-weight",ORIENTATION_GRANTED_KEY="efp-compass-permission-granted";
@@ -1,6 +1,6 @@
1
1
  /** The visited-URL trail (pathname + search per entry) — analytics referrer feed. */
2
2
  export declare function getLocationHistory(): string[];
3
- /** The current search string as the history sees it (`''` or `'?…'`). */
3
+ /** The app's current search (`''` or `'?…'`) — the platform's params filtered out. */
4
4
  export declare function currentSearch(): string;
5
5
  export declare function pushQuery(search: string): void;
6
6
  /**
@@ -1 +1 @@
1
- import{createBrowserHistory as h}from"history";import d from"../tools/logger";const t=h(),l=window.location.pathname,i=[];let r=!1,o=!1,c=0,f=()=>{},p;export function getLocationHistory(){return i}function n(e){return l+e}export function currentSearch(){return t.location.search}export function pushQuery(e){!r&&!o&&t.push(n(e))}export function replaceQuery(e){return r||o?!1:(t.replace(n(e)),!0)}export function disableUrlWrites(){r=!0}export function initUrlSync(e){r||=e.offHistory,f=e.onNavigate,!r&&n(t.location.search)===l&&i.push(n(t.location.search)),p=t.listen((u,s)=>{a(),!r&&(i.push(n(u.search)),d.log("history",s,u),s==="POP"&&f())})}export function destroyUrlSync(){r=!1,a(),p?.()}function a(){o=!1,window.clearTimeout(c)}export function goBack(){o=!0,window.clearTimeout(c),c=window.setTimeout(a,1e3),t.goBack()}
1
+ import{splitPlatformParams as s}from"@expofp/config";import{createBrowserHistory as d}from"history";import y from"../tools/logger";const t=d(),a=window.location.pathname,l=[];let i="",r=!1,c=!1,u=0,p=()=>{},h;export function getLocationHistory(){return l}function m(e){if(!i)return a+e;const o=s(e).search,n=o==="?"?"":o;return a+(n?`${n}&${i}`:`?${i}`)}export function currentSearch(){return s(t.location.search).search}export function pushQuery(e){!r&&!c&&t.push(m(e))}export function replaceQuery(e){return r||c?!1:(t.replace(m(e)),!0)}export function disableUrlWrites(){r=!0}export function initUrlSync(e){r||=e.offHistory,p=e.onNavigate,i=s(t.location.search).platform,!r&&!t.location.search&&l.push(a),h=t.listen((o,n)=>{f(),!r&&(l.push(a+o.search),y.log("history",n,o),n==="POP"&&p())})}export function destroyUrlSync(){r=!1,i="",f(),h?.()}function f(){c=!1,window.clearTimeout(u)}export function goBack(){c=!0,window.clearTimeout(u),u=window.setTimeout(f,1e3),t.goBack()}
@@ -0,0 +1,76 @@
1
+ import { type OutdoorPoiFilterState } from './outdoor-poi-filter';
2
+ import type RootStore from './RootStore';
3
+ /**
4
+ * A rendered outdoor PoI marker, shared between the place that creates it
5
+ * (`config-outdoor-poi`) and the consumer that renders it as native MapLibre
6
+ * symbol/cluster layers (`usePoiMarkers`).
7
+ *
8
+ * `icon` is the category pin — poiType glyph and Designer color baked in —
9
+ * rasterized once at devicePixelRatio and handed to `map.addImage`. (The
10
+ * selection pinhead is not per-marker: usePoiMarkers draws one shared image.)
11
+ * `center` is the PoI position in SVG/model coordinates (booth rect center);
12
+ * everything else about marker state (selection, filtering, clustering) is
13
+ * derived at render time from the stores, not stored here.
14
+ */
15
+ export interface PoiMarker {
16
+ boothId: number;
17
+ center: {
18
+ x: number;
19
+ y: number;
20
+ };
21
+ icon: ImageData;
22
+ }
23
+ /**
24
+ * Domain store for the current outdoor PoI markers. `config-outdoor-poi`
25
+ * publishes the rasterized markers here; `usePoiMarkers` renders them as
26
+ * native MapLibre layers, and dimming/filtering read them via MobX.
27
+ *
28
+ * Selection is not stored: {@link selectedMarkerId} derives it from
29
+ * `uiState.selectedBooths` (the single selected booth, if it has a marker),
30
+ * so `RootStore.clickBooth` / search selection are the only writers.
31
+ */
32
+ export default class PoiMarkerStore {
33
+ readonly rootStore: RootStore;
34
+ /**
35
+ * Backing box for {@link markers}, reference-observed (`deep: false`):
36
+ * PoiMarker holds raster data that must not be deep-observed. A box instead of
37
+ * an `@observable.ref` field because mobx 5's field-decorator typing
38
+ * predates TS standard decorators (the @-form fails to type-check), and the
39
+ * runtime `decorate()` alternative silently breaks under native class-field
40
+ * (define) semantics, which vitest's transform uses.
41
+ */
42
+ private readonly markersBox;
43
+ /**
44
+ * Monotonic counter bumped by {@link clear}. Async marker producers capture
45
+ * it before awaiting and compare before {@link addMany}, so icon loads that
46
+ * outlive a scene teardown/rebuild cannot repopulate the store with stale
47
+ * markers.
48
+ */
49
+ generation: number;
50
+ constructor(rootStore: RootStore);
51
+ /** The current markers; the array is replaced wholesale, never mutated. */
52
+ get markers(): readonly PoiMarker[];
53
+ /** Registers a batch of markers with a single change notification. */
54
+ addMany(newMarkers: readonly PoiMarker[]): void;
55
+ clear(): void;
56
+ /**
57
+ * The marker shown as the selection pinhead: the single selected booth, if
58
+ * exactly one booth is selected and it has an outdoor marker. Multi-select
59
+ * (routes, multi-booth exhibitors) shows no per-marker highlight.
60
+ */
61
+ get selectedMarkerId(): number | null;
62
+ /** Whether an outdoor marker is selected — suppresses venue dimming. */
63
+ get selectionActive(): boolean;
64
+ /**
65
+ * The active poiType filter narrowed to the markers it actually renders.
66
+ * Cached: it scans every booth, and the map reads it from several places
67
+ * (marker data, camera fit, dimming) on every selection or filter change.
68
+ */
69
+ get outdoorFilter(): OutdoorPoiFilterState;
70
+ /**
71
+ * Dimming is suppressed while an outdoor PoI filter or marker selection is
72
+ * active — the whole point of both is to make those markers stand out.
73
+ */
74
+ get dimSuppressed(): boolean;
75
+ }
76
+ //# sourceMappingURL=PoiMarkerStore.d.ts.map
@@ -0,0 +1 @@
1
+ import{__decorate as r}from"tslib";import{action as l,computed as s,observable as n}from"mobx";import{computeOutdoorPoiFilterState as d}from"./outdoor-poi-filter";export default class t{constructor(e){this.markersBox=n.box([],{deep:!1}),this.generation=0,this.rootStore=e}get markers(){return this.markersBox.get()}addMany(e){e.length&&this.markersBox.set([...this.markers,...e])}clear(){this.generation+=1,this.markersBox.set([])}get selectedMarkerId(){const e=[...this.rootStore.uiState.selectedBooths],o=e.length===1?e[0]:void 0;return o&&this.markers.some(i=>i.boothId===o.id)?o.id:null}get selectionActive(){return this.selectedMarkerId!==null}get outdoorFilter(){const{uiState:e,boothStore:o}=this.rootStore;return d(e.selectedPoiTypeFilters.map(i=>i.id),e.selectedCategoryFilters.length>0,o.booths,this.markers)}get dimSuppressed(){return this.outdoorFilter.active||this.selectionActive}}r([l],t.prototype,"addMany",null),r([l],t.prototype,"clear",null),r([s({keepAlive:!0})],t.prototype,"selectedMarkerId",null),r([s({keepAlive:!0})],t.prototype,"selectionActive",null),r([s({keepAlive:!0})],t.prototype,"outdoorFilter",null),r([s({keepAlive:!0})],t.prototype,"dimSuppressed",null);
@@ -12,6 +12,7 @@ import HeatmapStore from './HeatmapStore';
12
12
  import IntercomStore from './IntercomStore';
13
13
  import LayerStore from './LayerStore';
14
14
  import MaplibreStore from './MaplibreStore';
15
+ import PoiMarkerStore from './PoiMarkerStore';
15
16
  import PoiTypeStore from './PoiTypeStore';
16
17
  import RoutePlannerStore from './RoutePlannerStore';
17
18
  import RouteStore from './RouteStore';
@@ -38,6 +39,7 @@ export default class RootStore {
38
39
  readonly intercomStore: IntercomStore;
39
40
  readonly eventStore: EventStore;
40
41
  readonly poiTypeStore: PoiTypeStore;
42
+ readonly poiMarkerStore: PoiMarkerStore;
41
43
  readonly heatmapStore: HeatmapStore;
42
44
  readonly fuzzySearchEngineStore: FuzzySearchEngineStore;
43
45
  readonly categoryFilterStore: CategoryFilterStore;