@expofp/floorplan 0.0.0-experimental.2632d13 → 0.0.0-experimental.6dabc65

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 (29) hide show
  1. package/dist/browser/{GpsLoader-DwNSQv4V.js → GpsLoader-D9ghVrHk.js} +3 -3
  2. package/dist/browser/{KioskStore-DgP9k2lT.js → KioskStore-BY2LVJPr.js} +3 -3
  3. package/dist/browser/{LayerStore-DCwl80sb.js → LayerStore-Cdwr6Hsw.js} +2 -2
  4. package/dist/browser/{MaplibreAdapter-B-c-uOJf.js → MaplibreAdapter-aWJl2IuA.js} +55 -56
  5. package/dist/browser/{RouteStore-CuslHjhJ.js → RouteStore-DTRRmaH_.js} +1548 -740
  6. package/dist/browser/{SetKioskMode-CVD7sZLr.js → SetKioskMode-KMjCaliE.js} +2 -2
  7. package/dist/browser/{ShowKiosk-DuOS8tTO.js → ShowKiosk-C_gEEGg7.js} +2 -2
  8. package/dist/browser/{ViewerMenuPanel-Xj-8aVzf.js → ViewerMenuPanel-CbkSUP3L.js} +2 -2
  9. package/dist/browser/bundle.json +22 -25
  10. package/dist/browser/{components-D8dv3ezN.js → components-DRXsdUhs.js} +714 -714
  11. package/dist/browser/{create-live-plan-Ff4MkKcG.js → create-live-plan-DnaL_dh7.js} +385 -724
  12. package/dist/browser/{floorplan.loader-fOvLfGGf.js → floorplan.loader-151P9pJo.js} +3 -3
  13. package/dist/browser/{floorplan.ready-Bvj8hVzH.js → floorplan.ready-CCnzh5dy.js} +48 -48
  14. package/dist/browser/index.js +5 -5
  15. package/dist/browser/{venue-public-CH7uq9Xn.js → init-ui-DsRfN2rh.js} +5 -15
  16. package/dist/browser/{integrateKiosk-DhdxcN-Y.js → integrateKiosk-w_EetoNQ.js} +1 -1
  17. package/dist/browser/{journey-plan-cw-9rqLk.js → journey-plan-CEf1fFZz.js} +14 -14
  18. package/dist/browser/{kiosk-mode-Bqv2L5PO.js → kiosk-mode-Ck1FQGr9.js} +1 -1
  19. package/dist/browser/{kioskUrlParam-dw9tDQ6e.js → kioskUrlParam-BinDd3Gf.js} +1 -1
  20. package/dist/browser/{logDeviceInfo-D2Anqc6y.js → logDeviceInfo-OsKRXOu4.js} +3 -3
  21. package/dist/browser/{debounce-B4PlcNh4.js → venue-selection-DLUrexiA.js} +6 -16
  22. package/dist/browser/{viewport-juWifKNy.js → viewport-CBi835qx.js} +1 -1
  23. package/dist/esm/store/RouteStore.d.ts +10 -0
  24. package/dist/esm/store/RouteStore.js +43 -16
  25. package/dist/esm/store/VenueStore.d.ts +7 -0
  26. package/dist/esm/store/VenueStore.js +9 -0
  27. package/dist/esm/tools/settings.js +1 -1
  28. package/package.json +10 -10
  29. package/dist/browser/venues-Yq0wU18A.js +0 -447
@@ -9,6 +9,7 @@ import { getFpGeo } from '../data/fpGeo.js';
9
9
  import { getLayerSvg, getSvgArea } from '../data/svg.js';
10
10
  import { GaEventActions, sendEventToGa } from '../tools/gtag';
11
11
  import logger from '../tools/logger';
12
+ import settings from '../tools/settings';
12
13
  import { areLayersEnabled } from '../utils/areLayersEnabled';
13
14
  import { calcSpeed } from '../utils/calcSpeed';
14
15
  import { calcTravelTime } from '../utils/calcTravelTime';
@@ -18,6 +19,7 @@ import store, { layersStore, uiState } from '.';
18
19
  import { BoothBase } from './BoothStore';
19
20
  import { LayersMode } from './LayerStore';
20
21
  import { revealLayer } from './reveal-layer.js';
22
+ import { venueLevelForFix } from './VenueStore.js';
21
23
  /** A coordinate as the SDK may deliver it — `1.5`, or `"1,5"` from a comma locale. */
22
24
  function replaceCommasWithDot(value) {
23
25
  if (typeof value === 'string') {
@@ -107,9 +109,14 @@ export default class RouteStore {
107
109
  return;
108
110
  if (destinationReady) {
109
111
  void destinationReady.then(() => {
110
- if (selectRouteRequest === this.selectRouteRequest) {
111
- this.rootStore.moveToList(list, true);
112
- }
112
+ if (selectRouteRequest !== this.selectRouteRequest)
113
+ return;
114
+ // A route the engine has already drawn framed itself as it did (`onRouteUpdate`), and
115
+ // this focus, held back for the destination's level, would land after that fit and
116
+ // pull the camera onto the listed booths — from the blue dot, the destination alone.
117
+ if (this.routedRoute === route && this.routeLines.length)
118
+ return;
119
+ this.rootStore.moveToList(list, true);
113
120
  });
114
121
  }
115
122
  else {
@@ -172,6 +179,23 @@ export default class RouteStore {
172
179
  ?.filter((name, i, self) => self.indexOf(name) === i);
173
180
  return routeSteps(layers ?? [], this.campusLayersBox.get(), (name) => Boolean(store.layerStore.findLayer(name))).map((name, i) => ({ id: i + 1, layer: store.layerStore.findLayer(name) }));
174
181
  }
182
+ /**
183
+ * The floor a plan point stands on — a position fix, or a coordinate route endpoint. Floors
184
+ * belong to venues, so on a venue-model plan the outline the point lies in decides: outdoors it
185
+ * stands on none, whatever floor it reports; inside a venue it keeps the reported floor only when
186
+ * that floor is one of the venue's own levels, and otherwise takes the venue's
187
+ * (`venueLevelForFix`). Another hall's floor would scope the point to that hall — read as off a
188
+ * route right under it, and start a route "from here" at that hall's nearest walkway. Off a
189
+ * venue model the reported floor stands as is.
190
+ */
191
+ pointLayer(point, z) {
192
+ const reported = this.rootStore.layerStore.findLayer(z);
193
+ const venueStore = this.rootStore.venueStore;
194
+ if (!venueStore?.hasVenueModel)
195
+ return reported;
196
+ const venue = venueStore.venueAt(point);
197
+ return venue ? venueLevelForFix(venue, reported?.name).layer : null;
198
+ }
175
199
  /**
176
200
  * Used only by the SDK `getBooth(RouteWaypoint)` path for coord-form
177
201
  * waypoints (`floorplan.ready.tsx`). Internal callers prefer
@@ -181,7 +205,6 @@ export default class RouteStore {
181
205
  getNearestBooth(position) {
182
206
  if (!position)
183
207
  return null;
184
- const layerExists = this.rootStore.layerStore.findLayer(position.z);
185
208
  const gpsConfig = getFpGeo()?.properties.config;
186
209
  const isGpsFix = Boolean(position.lat && position.lng);
187
210
  const localPoint = gpsConfig && isGpsFix ? convertGpsToLocal(position, gpsConfig) : position;
@@ -190,15 +213,17 @@ export default class RouteStore {
190
213
  if (!localPoint || !isValidPointCoords(localPoint.x) || !isValidPointCoords(localPoint.y)) {
191
214
  return null;
192
215
  }
216
+ const layer = this.pointLayer(localPoint, position.z);
217
+ // Off a venue model an empty `z` can still match a layer by name, and such a floorless fix keeps
218
+ // every visible booth in play, as before; on one, the floor `pointLayer` decided is the answer.
219
+ const floorless = !this.rootStore.venueStore?.hasVenueModel && typeof position.z !== 'number' && !position.z;
193
220
  return (this.rootStore.boothStore.booths
194
221
  .filter((b) => {
195
- if (layersStore.mode === LayersMode.Default || !layerExists) {
222
+ if (this.rootStore.layerStore.mode === LayersMode.Default || !layer) {
196
223
  return b.visible && b.rect;
197
224
  }
198
225
  else {
199
- return (b.rect &&
200
- ((typeof position.z !== 'number' && !position.z && b.visible) ||
201
- layerExists.name === b.layer?.name));
226
+ return b.rect && ((floorless && b.visible) || layer.name === b.layer?.name);
202
227
  }
203
228
  })
204
229
  .sort((b1, b2) => pointDistance(localPoint, b1.rect.center) - pointDistance(localPoint, b2.rect.center))[0] || null);
@@ -276,7 +301,9 @@ export default class RouteStore {
276
301
  // name merely holds the number (13 → Hall13).
277
302
  const floors = this.rootStore.layerStore.layers.filter((layer) => !layer.rootParent && !layer.frozen);
278
303
  const noFloorAtIndex = typeof point.z === 'number' && !floors[point.z];
279
- if ((data.ignoreUnknownFloorIndex === true && noFloorAtIndex) || !areLayersEnabled()) {
304
+ if (settings.EXPO === 'eurotier2026' ||
305
+ (data.ignoreUnknownFloorIndex === true && noFloorAtIndex) ||
306
+ !areLayersEnabled()) {
280
307
  point.z = undefined;
281
308
  }
282
309
  }
@@ -292,13 +319,13 @@ export default class RouteStore {
292
319
  this.currentPosition = null;
293
320
  return;
294
321
  }
295
- // Floors belong to venues: a fix outside every venue outline stands on none, whatever floor it
296
- // reports and whichever floor the route is on. A floor it is not on would scope it to that
297
- // hall — read as off a route that is right under it, and start a route from inside the hall.
298
- const venueStore = this.rootStore.venueStore;
299
- const outdoors = !!venueStore?.hasVenueModel && !venueStore.venueAt(position);
300
- const layer = outdoors ? null : store.layerStore.findLayer(point.z);
301
- const newPosition = new CurrentPosition(position.x, position.y, outdoors ? undefined : layer?.name || this.currentRouteLayer?.name, calculateRelativeBearing(position), point.lat, point.lng);
322
+ const layer = this.pointLayer(position, point.z);
323
+ // Off a venue model, a fix without a floor takes the route's; on one, `pointLayer` has
324
+ // already decided — no floor outdoors, the venue's own inside an outline.
325
+ const routeLayerFallback = this.rootStore.venueStore?.hasVenueModel
326
+ ? undefined
327
+ : this.currentRouteLayer?.name;
328
+ const newPosition = new CurrentPosition(position.x, position.y, layer?.name || routeLayerFallback, calculateRelativeBearing(position), point.lat, point.lng);
302
329
  let isPositionAndRouteOnTheSameLayer = !this.routeLines?.length;
303
330
  if (layer && this.routeLines?.length) {
304
331
  isPositionAndRouteOnTheSameLayer = !!this.routeLines.find((line) => line.p0.layer === layer.name || line.p1.layer === layer.name);
@@ -94,6 +94,13 @@ export declare class Venue {
94
94
  /** Full floor detail currently visible (R6); unevaluated counts as visible. */
95
95
  get detailVisible(): boolean;
96
96
  }
97
+ /**
98
+ * The level of `venue` that a position fix inside it stands on: the reported floor when it is one
99
+ * of the venue's own levels, otherwise the level the venue shows. The outline a fix lies in names
100
+ * its venue beyond doubt; the floor it reports can be wrong — a positioning system may carry an
101
+ * indoor floor over onto later GPS fixes, or number the floors its own way.
102
+ */
103
+ export declare function venueLevelForFix(venue: Pick<Venue, 'levels' | 'activeLevel'>, reportedLayerName: string | undefined): VenueLevel;
97
104
  /**
98
105
  * Owns the venue model of a multi-venue plan: the venue list, viewport focus,
99
106
  * and each venue's active level. Levels stay owned by LayerStore; a venue
@@ -89,6 +89,15 @@ export class Venue {
89
89
  return this._presentationState.get()?.detailVisible ?? true;
90
90
  }
91
91
  }
92
+ /**
93
+ * The level of `venue` that a position fix inside it stands on: the reported floor when it is one
94
+ * of the venue's own levels, otherwise the level the venue shows. The outline a fix lies in names
95
+ * its venue beyond doubt; the floor it reports can be wrong — a positioning system may carry an
96
+ * indoor floor over onto later GPS fixes, or number the floors its own way.
97
+ */
98
+ export function venueLevelForFix(venue, reportedLayerName) {
99
+ return venue.levels.find((level) => level.layer.name === reportedLayerName) ?? venue.activeLevel;
100
+ }
92
101
  /**
93
102
  * Owns the venue model of a multi-venue plan: the venue list, viewport focus,
94
103
  * and each venue's active level. Levels stay owned by LayerStore; a venue
@@ -64,7 +64,7 @@ class Settings extends FpSettings {
64
64
  */
65
65
  function buildSettings() {
66
66
  let settings = new Settings();
67
- if (settings.EXPO.startsWith('sxsw2024')) {
67
+ if (settings.EXPO === 'sxsw2024') {
68
68
  settings.colors.booths.selected = '#FF6400';
69
69
  settings.colors.booths.seectedLight = '#808080';
70
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expofp/floorplan",
3
- "version": "0.0.0-experimental.2632d13",
3
+ "version": "0.0.0-experimental.6dabc65",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/expofp/efp-app.git",
@@ -69,15 +69,15 @@
69
69
  "tslib": "^2.3.0",
70
70
  "uuid": "^9.0.1",
71
71
  "zod": "4.4.3",
72
- "@expofp/config": "0.0.0-experimental.2632d13",
73
- "@expofp/debug": "0.0.0-experimental.2632d13",
74
- "@expofp/geometry": "0.0.0-experimental.2632d13",
75
- "@expofp/renderer": "0.0.0-experimental.2632d13",
76
- "@expofp/resolve": "0.0.0-experimental.2632d13",
77
- "@expofp/schema": "0.0.0-experimental.2632d13",
78
- "@expofp/ui": "0.0.0-experimental.2632d13",
79
- "@expofp/utils": "0.0.0-experimental.2632d13",
80
- "@expofp/wayfinding": "0.0.0-experimental.2632d13"
72
+ "@expofp/config": "0.0.0-experimental.6dabc65",
73
+ "@expofp/debug": "0.0.0-experimental.6dabc65",
74
+ "@expofp/geometry": "0.0.0-experimental.6dabc65",
75
+ "@expofp/renderer": "0.0.0-experimental.6dabc65",
76
+ "@expofp/resolve": "0.0.0-experimental.6dabc65",
77
+ "@expofp/schema": "0.0.0-experimental.6dabc65",
78
+ "@expofp/ui": "0.0.0-experimental.6dabc65",
79
+ "@expofp/utils": "0.0.0-experimental.6dabc65",
80
+ "@expofp/wayfinding": "0.0.0-experimental.6dabc65"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@babel/plugin-proposal-decorators": "^8.0.2",
@@ -1,447 +0,0 @@
1
- (function() {
2
- try {
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.45.6" };
5
- var t = new e.Error().stack;
6
- t && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[t] = "5f4c3e09-f59c-417b-b628-a47d62512eb3", e._sentryDebugIdIdentifier = "sentry-dbid-5f4c3e09-f59c-417b-b628-a47d62512eb3");
7
- } catch {}
8
- })();
9
- import { _n as e, gn as t, mn as n, un as r } from "./LayerStore-DCwl80sb.js";
10
- //#region src/data/venues.ts
11
- var i = /^[a-z0-9_-]+$/, a = ["scene", "marker"], o = 11, s = 10;
12
- function c(e, t) {
13
- return e * s >= t * o;
14
- }
15
- function l(e) {
16
- return e === 60 ? 66 : Math.ceil(e * o / s);
17
- }
18
- var u = /* @__PURE__ */ new Set([
19
- "id",
20
- "name",
21
- "order",
22
- "levels",
23
- "contour",
24
- "markerPoint",
25
- "detailMinSizePx",
26
- "markerMaxSizePx",
27
- "layers",
28
- "entrances",
29
- "campusViewbox"
30
- ]), d = /* @__PURE__ */ new Set([
31
- "layer",
32
- "ordinal",
33
- "name",
34
- "initial"
35
- ]), f = /* @__PURE__ */ new Set([
36
- "layer",
37
- "point",
38
- "name"
39
- ]), p = /* @__PURE__ */ new Set([
40
- "layer",
41
- "render",
42
- "replacesDefault",
43
- "suppressesLabel",
44
- "minSizePx",
45
- "maxSizePx"
46
- ]), m = (e, t) => e < t ? -1 : +(e > t), h = (e) => typeof e == "object" && !!e && !Array.isArray(e), g = (e) => typeof e == "number" && Number.isFinite(e), _ = (e) => typeof e == "string" && e.length > 0, v = (e) => h(e) && g(e.x) && g(e.y), y = (e) => h(e) && g(e.x) && g(e.y) && g(e.width) && g(e.height) && e.width > 0 && e.height > 0;
47
- function b(e) {
48
- try {
49
- let t = JSON.stringify(e);
50
- return t === void 0 ? String(e) : t;
51
- } catch {
52
- return String(e);
53
- }
54
- }
55
- function x(e) {
56
- for (let t of e) try {
57
- console.warn("parseVenues:", `${t.code} (${t.effect}) ${t.path || "(root)"}: ${t.message}; ${t.consequence}`);
58
- } catch {}
59
- }
60
- function S(e, t, n, r = null) {
61
- return x(t), {
62
- venues: e,
63
- diagnostics: t,
64
- quarantinedLayerNames: n,
65
- campusViewbox: r
66
- };
67
- }
68
- function C(e, t, n, r) {
69
- let i = (e, t, n) => (t.x - e.x) * (n.y - e.y) - (t.y - e.y) * (n.x - e.x), a = i(n, r, e), o = i(n, r, t), s = i(e, t, n), c = i(e, t, r);
70
- if ((a > 0 && o < 0 || a < 0 && o > 0) && (s > 0 && c < 0 || s < 0 && c > 0)) return !0;
71
- let l = (e, t, n) => Math.min(e.x, t.x) <= n.x && n.x <= Math.max(e.x, t.x) && Math.min(e.y, t.y) <= n.y && n.y <= Math.max(e.y, t.y);
72
- return a === 0 && l(n, r, e) || o === 0 && l(n, r, t) || s === 0 && l(e, t, n) || c === 0 && l(e, t, r);
73
- }
74
- function w(e) {
75
- if (!Array.isArray(e)) return { issue: "is not an array" };
76
- if (e.length < 3) return { issue: `has ${e.length} point(s); a ring needs at least 3` };
77
- if (!e.every(v)) return { issue: "contains a non-finite or malformed point" };
78
- let t = e.map((e) => ({
79
- x: e.x,
80
- y: e.y
81
- })), n = t[0], i = t[t.length - 1];
82
- if (n.x === i.x && n.y === i.y && t.pop(), t.length < 3) return { issue: `has ${t.length} point(s); a ring needs at least 3` };
83
- let { width: a, height: o } = r.fromPoints(t).size;
84
- if (a === 0 || o === 0) return { issue: "is degenerate (zero width or height)" };
85
- for (let e = 0; e < t.length; e++) {
86
- let n = t[e], r = t[(e + 1) % t.length];
87
- for (let i = e + 1; i < t.length; i++) if (!(i === e || (i + 1) % t.length === e || (e + 1) % t.length === i) && C(n, r, t[i], t[(i + 1) % t.length])) return { issue: "is self-intersecting; v1 accepts one simple ring only (no holes, no multi-part)" };
88
- }
89
- let s = 0;
90
- for (let e = 0; e < t.length; e++) {
91
- let n = t[e], r = t[(e + 1) % t.length];
92
- s += n.x * r.y - r.x * n.y;
93
- }
94
- return s === 0 ? { issue: "is degenerate (zero area)" } : { ring: t };
95
- }
96
- function T(e, r) {
97
- let i = [];
98
- for (let t of e) {
99
- var a;
100
- if (!t.surviving) continue;
101
- let e = r.get(t.value.layer), o = (a = e == null ? void 0 : e.rect) == null ? e == null ? void 0 : e.viewbox : a;
102
- !o || o.area <= 0 || i.push(...n(o).map((e) => ({
103
- x: e.x,
104
- y: e.y
105
- })));
106
- }
107
- return t(i);
108
- }
109
- function E(e, t, n = []) {
110
- try {
111
- return D(e, t, n);
112
- } catch {
113
- return S([], [{
114
- code: "venues-payload-invalid",
115
- path: "venues",
116
- message: "could not be parsed",
117
- consequence: "plan loads as single-venue",
118
- effect: "dropped"
119
- }], []);
120
- }
121
- }
122
- function D(t, n, o) {
123
- let s = [], x = (e) => (t, n, r, i) => s.push({
124
- code: t,
125
- path: n,
126
- message: r,
127
- consequence: i,
128
- effect: e
129
- }), C = x("dropped"), E = x("fallback"), D = x("clamped"), O = x("advisory"), k = (e, t, n) => {
130
- for (let r of Object.keys(t)) n.has(r) || O("unknown-key", `${e}.${r}`, "is not a contract field", "ignored by the SDK");
131
- }, A = (e) => {
132
- let t = s.length;
133
- try {
134
- return e();
135
- } finally {
136
- s.length = t;
137
- }
138
- }, j = /* @__PURE__ */ new Set();
139
- for (let e of o) for (let t of e) j.add(t.layer);
140
- if (t == null) return S([], s, []);
141
- if (!h(t)) return C("venues-payload-invalid", "", "payload is not an object", "nothing to parse"), S([], s, []);
142
- let M = t.venues;
143
- if (M === void 0) return S([], s, []);
144
- if (t.venuesVersion !== void 0 && t.venuesVersion !== 1) return C("venues-version-unsupported", "venuesVersion", `payload version ${b(t.venuesVersion)} is unsupported; SDK supports version 1`, "whole venues array ignored; plan loads as single-venue"), S([], s, []);
145
- if (!Array.isArray(M)) return C("venues-payload-invalid", "venues", "is not an array", "plan loads as single-venue"), S([], s, []);
146
- let N = /* @__PURE__ */ new Map(), P = /* @__PURE__ */ new Map(), F = /* @__PURE__ */ new Map();
147
- M.forEach((e, t) => {
148
- if (!h(e) || !_(e.name)) return;
149
- let n = `venues[${t}]`, r = e.name.toLowerCase(), i = P.get(r);
150
- i ? F.set(n, i) : P.set(r, n);
151
- });
152
- let I = M.map((e, t) => {
153
- var r, o;
154
- let s = `venues[${t}]`;
155
- if (!h(e)) return C("venue-identity-invalid", s, "is not an object", "venue dropped"), {
156
- at: s,
157
- label: s,
158
- claimable: !1,
159
- order: t,
160
- levels: [],
161
- aux: [],
162
- entrances: [],
163
- expectedSceneLayers: [],
164
- referencedLayers: []
165
- };
166
- k(s, e, u);
167
- let m = !0, y = e.id;
168
- _(y) ? (i.test(y) || (C("venue-identity-invalid", `${s}.id`, `"${y}" must match ${i} (lowercase alphanumerics, hyphen, underscore)`, "id is used as a MapLibre feature id, a style-image id and a ?camera[venue]= deep-link value"), m = !1), N.has(y) ? (C("venue-id-duplicate", `${s}.id`, `"${y}" duplicates ${N.get(y)}`, "this venue dropped"), m = !1) : N.set(y, s)) : (C("venue-identity-invalid", `${s}.id`, "is missing or not a non-empty string", "venue dropped"), m = !1);
169
- let x = _(y) ? `"${y}"` : s, S = e.name;
170
- _(S) ? F.has(s) && O("venue-name-duplicate", `${s}.name`, `"${S}" duplicates the name of ${F.get(s)} (case-insensitive)`, "nothing dropped — two identical rows in the venue switch, ambiguous search results") : (C("venue-identity-invalid", `${s}.name`, "is missing or not a non-empty string", "venue dropped"), m = !1);
171
- let T = t;
172
- Number.isInteger(e.order) ? T = e.order : E("venue-order-invalid", `${s}.order`, e.order === void 0 ? "is missing" : "is not an integer", "falls back to array position; order is contractually required (§9)");
173
- let A = [], M = (e, t = !1) => {
174
- _(e) && !e.startsWith("WF") && t && !A.includes(e) && A.push(e);
175
- }, P = [];
176
- if (!Array.isArray(e.levels) || e.levels.length === 0) C("venue-levels-missing", `${s}.levels`, "is missing or empty", "venue dropped"), m = !1;
177
- else {
178
- e.levels.forEach((e, t) => {
179
- let r = `${s}.levels[${t}]`;
180
- if (!h(e)) {
181
- C("level-entry-invalid", r, "is not an object", "level dropped");
182
- return;
183
- }
184
- k(r, e, d), M(e.layer, n.has(e.layer));
185
- let i = !0;
186
- _(e.layer) ? (n.has(e.layer) || (C("level-layer-unknown", `${r}.layer`, `"${e.layer}" does not exist in the plan`, `level dropped; venue ${x} loses this floor (check for a rename or typo)`), i = !1), e.layer.startsWith("WF") && (C("level-layer-wayfinding", `${r}.layer`, `"${e.layer}" is a wayfinding layer`, "WF* layers are excluded before the venue model sees them — level dropped"), i = !1)) : (C("level-layer-invalid", `${r}.layer`, "is missing or not a non-empty string", "level dropped"), i = !1), Number.isInteger(e.ordinal) || (C("level-ordinal-invalid", `${r}.ordinal`, "is missing or not an integer", "level dropped; ordinal is required (0 = ground, -1 = basement)"), i = !1), e.name !== void 0 && !_(e.name) && E("level-field-invalid", `${r}.name`, "is not a non-empty string", "falls back to the layer's description"), e.initial !== void 0 && typeof e.initial != "boolean" && E("level-field-invalid", `${r}.initial`, "is not a boolean", "ignored"), P.push({
187
- value: {
188
- layer: _(e.layer) ? e.layer : "",
189
- ordinal: Number.isInteger(e.ordinal) ? e.ordinal : 0,
190
- name: _(e.name) ? e.name : void 0,
191
- initial: typeof e.initial == "boolean" ? e.initial : void 0
192
- },
193
- at: r,
194
- ok: i,
195
- surviving: !1
196
- });
197
- });
198
- let t = /* @__PURE__ */ new Map();
199
- for (let e of P) {
200
- if (!e.ok) continue;
201
- let n = e.value.ordinal, r = t.get(n);
202
- r ? (C("level-ordinal-duplicate", `${e.at}.ordinal`, `${n} duplicates ${r}`, "level dropped; ordinals are unique within a venue"), e.ok = !1) : t.set(n, e.at);
203
- }
204
- }
205
- let I;
206
- if (e.contour !== void 0) {
207
- let t = w(e.contour);
208
- t.issue ? E("contour-invalid", `${s}.contour`, t.issue, "falls back to the scene layer's geometry, then to the hull of level rects") : I = t.ring;
209
- }
210
- let L;
211
- e.markerPoint !== void 0 && (v(e.markerPoint) ? L = {
212
- x: e.markerPoint.x,
213
- y: e.markerPoint.y
214
- } : E("venue-marker-point-invalid", `${s}.markerPoint`, "is not a finite {x, y} point", "falls back to the contour centroid"));
215
- let R;
216
- e.detailMinSizePx !== void 0 && (!g(e.detailMinSizePx) || e.detailMinSizePx <= 0 ? E("detail-min-size-invalid", `${s}.detailMinSizePx`, "is not a positive finite number", "default 240 used") : R = e.detailMinSizePx);
217
- let z;
218
- if (e.markerMaxSizePx !== void 0) {
219
- let t = R === void 0 ? 240 : Math.max(66, R);
220
- !g(e.markerMaxSizePx) || e.markerMaxSizePx <= 0 ? E("marker-max-size-invalid", `${s}.markerMaxSizePx`, "is not a positive finite number", "default 60 used") : e.markerMaxSizePx >= t ? E("marker-max-size-inverted", `${s}.markerMaxSizePx`, `${e.markerMaxSizePx} is at or above the venue's resolved detailMinSizePx of ${t}`, "default 60 used, then the detail-edge clamp applies") : z = e.markerMaxSizePx;
221
- }
222
- let B = (r = z) == null ? 60 : r;
223
- if (R !== void 0 && !c(R, B)) {
224
- let e = l(B);
225
- D("detail-min-size-clamped", `${s}.detailMinSizePx`, `${R} is below the ${e}px marker/scene sticky enter edge`, `clamped to ${e}`), R = e;
226
- }
227
- let V = (o = R) == null ? 240 : o, H = [], U = [];
228
- e.layers !== void 0 && (Array.isArray(e.layers) ? e.layers.forEach((e, t) => {
229
- let r = `${s}.layers[${t}]`;
230
- if (!h(e)) {
231
- C("aux-entry-invalid", r, "is not an object", "entry dropped");
232
- return;
233
- }
234
- k(r, e, p), _(e.layer) && e.render === "scene" && (e.replacesDefault === void 0 || e.replacesDefault === !0) && U.push(e.layer);
235
- let i = _(e.layer) && (n.has(e.layer) || j.has(e.layer));
236
- M(e.layer, i);
237
- let o = !0;
238
- _(e.layer) ? (i || (C("aux-layer-unknown", `${r}.layer`, `"${e.layer}" does not exist in the plan`, "entry dropped; venue falls back to the procedural appearance"), o = !1), e.layer.startsWith("WF") && (C("aux-layer-wayfinding", `${r}.layer`, `"${e.layer}" is a wayfinding layer`, "WF* layers are excluded before the venue model sees them — entry dropped"), o = !1)) : (C("aux-layer-invalid", `${r}.layer`, "is missing or not a non-empty string", "entry dropped"), o = !1);
239
- let c = a.includes(e.render);
240
- c || (C("aux-entry-invalid", `${r}.render`, `is ${b(e.render)}, expected "scene" or "marker"`, "entry dropped"), o = !1), e.replacesDefault !== void 0 && typeof e.replacesDefault != "boolean" && (C("aux-entry-invalid", `${r}.replacesDefault`, "is not a boolean", "entry dropped"), o = !1), e.suppressesLabel !== void 0 && typeof e.suppressesLabel != "boolean" && (C("aux-entry-invalid", `${r}.suppressesLabel`, "is not a boolean", "entry dropped"), o = !1), e.minSizePx !== void 0 && (!g(e.minSizePx) || e.minSizePx < 0) && (C("aux-entry-invalid", `${r}.minSizePx`, "is not a non-negative finite number", "entry dropped"), o = !1), e.maxSizePx !== void 0 && e.maxSizePx !== "detail" && (!g(e.maxSizePx) || e.maxSizePx < 0) && (C("aux-entry-invalid", `${r}.maxSizePx`, "is not a non-negative finite number or the literal \"detail\"", "entry dropped"), o = !1), g(e.minSizePx) && g(e.maxSizePx) && e.minSizePx >= 0 && e.maxSizePx >= 0 && e.minSizePx > e.maxSizePx && (C("aux-range-inverted", r, `minSizePx ${e.minSizePx} exceeds maxSizePx ${e.maxSizePx}`, "entry dropped"), o = !1);
241
- let l = c ? e.render : "scene", u = g(e.minSizePx) && e.minSizePx >= 0 ? e.minSizePx : l === "marker" ? 0 : B, d = e.maxSizePx !== void 0 && (e.maxSizePx === "detail" || g(e.maxSizePx)) ? e.maxSizePx : l === "scene" ? "detail" : B;
242
- c && (d === "detail" ? u >= V : u > d) && (C("aux-range-never-visible", r, `resolved range ${u}..${d} can never render`, "entry dropped; the procedural fallback for this render mode is restored"), o = !1), c && l === "scene" && g(e.maxSizePx) && O("aux-max-size-numeric", `${r}.maxSizePx`, `is the hard edge ${e.maxSizePx} rather than "detail"`, "a static edge cannot follow the ±10% detail hysteresis — expect flicker and brief overlap with the floor plan"), H.push({
243
- value: {
244
- layer: _(e.layer) ? e.layer : "",
245
- render: l,
246
- replacesDefault: typeof e.replacesDefault == "boolean" ? e.replacesDefault : void 0,
247
- suppressesLabel: typeof e.suppressesLabel == "boolean" ? e.suppressesLabel : void 0,
248
- minSizePx: g(e.minSizePx) ? e.minSizePx : void 0,
249
- maxSizePx: e.maxSizePx === "detail" || g(e.maxSizePx) ? e.maxSizePx : void 0
250
- },
251
- at: r,
252
- ok: o,
253
- surviving: !1
254
- });
255
- }) : E("aux-layers-invalid", `${s}.layers`, "is not an array", "ignored; procedural appearance used"));
256
- let W = new Set((Array.isArray(e.levels) ? e.levels : []).filter(h).map((e) => e.layer).filter(_)), G = [];
257
- return e.entrances !== void 0 && (Array.isArray(e.entrances) ? e.entrances.forEach((e, t) => {
258
- let n = `${s}.entrances[${t}]`;
259
- if (!h(e)) {
260
- C("entrance-entry-invalid", n, "is not an object", "entrance dropped");
261
- return;
262
- }
263
- k(n, e, f);
264
- let r = !0;
265
- _(e.layer) ? W.has(e.layer) || (C("entrance-layer-foreign", `${n}.layer`, `"${e.layer}" is not a level of venue ${x}`, "entrance dropped; an entrance stands on one of its own venue’s levels"), r = !1) : (C("entrance-layer-invalid", `${n}.layer`, "is missing or not a non-empty string", "entrance dropped"), r = !1), v(e.point) || (C("entrance-entry-invalid", `${n}.point`, "is missing or not a finite {x, y} point", "entrance dropped; an entrance is a point before it is anything else"), r = !1), e.name !== void 0 && !_(e.name) && E("entrance-field-invalid", `${n}.name`, "is not a non-empty string", "falls back to the venue’s own name"), !(!r || !_(e.layer) || !v(e.point)) && G.push({
266
- value: {
267
- layer: e.layer,
268
- point: {
269
- x: e.point.x,
270
- y: e.point.y
271
- },
272
- name: _(e.name) ? e.name : void 0
273
- },
274
- at: n
275
- });
276
- }) : E("entrances-invalid", `${s}.entrances`, "is not an array", "ignored; the venue keeps marker-point targeting")), {
277
- at: s,
278
- id: _(y) ? y : void 0,
279
- name: _(S) ? S : void 0,
280
- label: x,
281
- claimable: m,
282
- order: T,
283
- levels: P,
284
- aux: H,
285
- entrances: G,
286
- expectedSceneLayers: U,
287
- contour: I,
288
- markerPoint: L,
289
- detailMinSizePx: R,
290
- markerMaxSizePx: z,
291
- referencedLayers: A,
292
- campusViewbox: e.campusViewbox
293
- };
294
- }), L = /* @__PURE__ */ new Set(), R = [...I].sort((e, t) => {
295
- var n, r;
296
- return e.order - t.order || m((n = e.id) == null ? "" : n, (r = t.id) == null ? "" : r);
297
- }), z = null, B;
298
- for (let e of R) {
299
- if (e.campusViewbox === void 0) continue;
300
- let t = `${e.at}.campusViewbox`;
301
- if (B) {
302
- C("campus-viewbox-duplicate", t, `${B.at} already carries the campus viewbox`, "this venue's value is ignored; the first carrier by order wins");
303
- continue;
304
- }
305
- B = e;
306
- let n = e.campusViewbox;
307
- y(n) ? z = new r(n.x, n.y, n.width, n.height) : E("campus-viewbox-invalid", t, "is not an {x, y, width, height} of finite numbers with a positive width and height", "the campus is framed by the union of the venue footprints");
308
- }
309
- let V = () => {
310
- let e = /* @__PURE__ */ new Map();
311
- for (let e of I) {
312
- e.parsed = void 0;
313
- for (let t of e.levels) t.surviving = !1;
314
- for (let t of e.aux) t.surviving = !1;
315
- }
316
- for (let t of R) if (!(!t.claimable || !t.id || !t.name || L.has(t))) for (let n of t.levels) {
317
- if (!n.ok) continue;
318
- let r = n.value.layer, i = e.get(r);
319
- if (i) {
320
- C("level-layer-claimed", `${n.at}.layer`, `"${r}" is already used by ${i.label} (${i.role})`, "level dropped; a layer belongs to at most one venue and one role");
321
- continue;
322
- }
323
- e.set(r, {
324
- label: t.label,
325
- role: "level"
326
- }), n.surviving = !0;
327
- }
328
- for (let t of R) {
329
- if (!t.claimable || !t.id || !t.name || L.has(t) || !t.levels.some((e) => e.surviving)) continue;
330
- let n = 0;
331
- for (let r of t.aux) {
332
- if (!r.ok) continue;
333
- let i = r.value, a = e.get(i.layer);
334
- if (a) {
335
- C("aux-layer-claimed", `${r.at}.layer`, `"${i.layer}" is already used by ${a.label} (${a.role})`, "entry dropped; a layer is a level, an aux layer, or neither — never two");
336
- continue;
337
- }
338
- if (i.render === "marker" && n > 0) {
339
- C("aux-marker-duplicate", `${r.at}.render`, "is a second marker layer for this venue", "at most one per venue; extras dropped, the first wins");
340
- continue;
341
- }
342
- e.set(i.layer, {
343
- label: t.label,
344
- role: "aux"
345
- }), r.surviving = !0, i.render === "marker" && n++;
346
- }
347
- }
348
- return e;
349
- }, H = (e) => {
350
- var t;
351
- if (e.contour) return e.contour;
352
- let r = I.indexOf(e), i = e.aux.filter((e) => e.ok && e.value.render === "scene" && e.value.replacesDefault !== !1), a = new Map(i.filter((e) => e.surviving).map((e) => [e.value.layer, e])), s = [];
353
- for (let e of (t = o[r]) == null ? [] : t) {
354
- let t = a.get(e.layer);
355
- if (!(t != null && t.surviving)) continue;
356
- let n = (n) => E("footprint-source-unusable", `${t.at}.layer`, `scene layer "${e.layer}" ${n}`, "the next valid replacing scene is tried, then the level-rect hull"), { extraction: r } = e;
357
- if (!r.ring) {
358
- n(r.unusableElementKinds.length > 0 ? `draws no usable <path>; only paths are footprint sources, and it draws ${r.unusableElementKinds.map((e) => `<${e}>`).join(", ")}` : "could not supply a valid contour");
359
- continue;
360
- }
361
- let i = w(r.ring);
362
- if (!i.ring) {
363
- var c;
364
- n((c = i.issue) == null ? "could not supply a valid contour" : c);
365
- continue;
366
- }
367
- s.push({
368
- candidate: t,
369
- layer: e.layer,
370
- ring: i.ring,
371
- boundsFallback: r.boundsFallback
372
- });
373
- }
374
- s.length > 1 && O("footprint-source-ambiguous", `${e.at}.layers`, `multiple replacing scene layers provide contours: ${s.map(({ layer: e }) => `"${e}"`).join(", ")}`, `the first in plan-layer order, "${s[0].layer}", wins`);
375
- let l = s[0];
376
- if (l) return l.boundsFallback && E("footprint-bounding-box", `${l.candidate.at}.layer`, `scene layer "${l.layer}" uses its bounding box for the venue contour`, "camera, tap target, and size bounds may extend beyond the artwork"), l.ring;
377
- let u = T(e.levels, n);
378
- return u.length >= 3 && e.expectedSceneLayers.length > 0 && E("footprint-source-fallthrough", `${e.at}.contour`, "replacing scene contour unavailable; using the level-rect hull", "bounds, camera target, tap target, and the size axis changed source"), u;
379
- };
380
- for (;;) {
381
- let e = A(() => (V(), R.find((e) => e.claimable && !L.has(e) && e.levels.some((e) => e.surviving) && H(e).length < 3)));
382
- if (!e) break;
383
- H(e), C("footprint-underivable", `${e.at}.contour`, "no valid polygon can be derived", `venue ${e.label} dropped entirely`), L.add(e);
384
- }
385
- let U = V();
386
- for (let t of I) {
387
- var W, G;
388
- if (!t.claimable || !t.id || !t.name || L.has(t)) continue;
389
- let n = t.levels.filter((e) => e.surviving);
390
- if (n.length === 0) {
391
- C("venue-levels-all-dropped", `${t.at}.levels`, "no level survives validation", `venue ${t.label} dropped entirely`);
392
- continue;
393
- }
394
- let i = H(t), a = t.levels.filter((e) => e.value.initial === !0), o = n.filter((e) => e.value.initial === !0);
395
- a.some((e) => !e.surviving) && E("level-initial-dropped", `${a.find((e) => !e.surviving).at}.initial`, "initial level was dropped", "the lowest surviving ordinal is initial"), t.levels.filter((e) => e.value.ordinal === 0).length > 0 && !n.some((e) => e.value.ordinal === 0) && O("level-ground-dropped", `${t.at}.levels`, "the ordinal 0 (ground) level was dropped", "cross-venue routing into this venue is likely broken (§13); the venue also boots on an upper floor"), o.length > 1 && O("level-initial-duplicate", `${t.at}.levels`, `${o.length} levels are marked initial`, "at most one per venue; the SDK takes the first");
396
- let s = (W = o[0]) == null ? n.reduce((e, t) => t.value.ordinal < e.value.ordinal ? t : e) : W, c = new Set(n.map((e) => e.value.layer)), l = [];
397
- for (let e of t.entrances) {
398
- if (!c.has(e.value.layer)) {
399
- C("entrance-level-dropped", `${e.at}.layer`, `level "${e.value.layer}" did not survive validation`, "entrance dropped; the venue falls back to its remaining doors, then to marker-point targeting");
400
- continue;
401
- }
402
- l.push({ ...e.value });
403
- }
404
- let u = i.map((e) => ({
405
- x: e.x,
406
- y: e.y
407
- }));
408
- t.parsed = {
409
- id: t.id,
410
- name: t.name,
411
- order: t.order,
412
- levels: n.map((e) => ({
413
- layer: e.value.layer,
414
- ordinal: e.value.ordinal,
415
- name: e.value.name,
416
- initial: e === s
417
- })),
418
- contour: u,
419
- markerPoint: (G = t.markerPoint) == null ? e(u) : G,
420
- bounds: r.fromPoints(u),
421
- detailMinSizePx: t.detailMinSizePx,
422
- markerMaxSizePx: t.markerMaxSizePx,
423
- entrances: l,
424
- auxLayers: t.aux.filter((e) => e.surviving).map(({ value: e }) => {
425
- var t, n;
426
- let r = (t = e.replacesDefault) == null || t;
427
- return {
428
- layer: e.layer,
429
- render: e.render,
430
- replacesDefault: r,
431
- suppressesLabel: (n = e.suppressesLabel) == null ? e.render === "scene" && r : n,
432
- minSizePx: e.minSizePx,
433
- maxSizePx: e.maxSizePx
434
- };
435
- })
436
- };
437
- }
438
- let K = [];
439
- for (let e of I) if (!e.parsed) for (let t of e.referencedLayers) K.includes(t) || K.push(t);
440
- let q = [];
441
- for (let e of I) e.parsed && q.push(e.parsed);
442
- if (M.length > 0 && q.length === 0) return C("venues-all-dropped", "venues", "no venue survived validation", "plan loads as single-venue"), S([], s, []);
443
- let J = K.filter((e) => !U.has(e));
444
- return J.length > 0 && C("plan-layers-quarantined", "venues", `quarantined unclaimed layer${J.length === 1 ? "" : "s"}: ${J.map((e) => `"${e}"`).join(", ")}`, "hidden from venue and ordinary layer rendering"), S(q, s, J, z);
445
- }
446
- //#endregion
447
- export { l as n, E as r, m as t };