@expofp/floorplan 0.0.0-experimental.2d6c681 → 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 (41) hide show
  1. package/dist/browser/{CookieConsent-BIsWzAiP.js → CookieConsent-DYjf8elV.js} +1 -1
  2. package/dist/browser/{Debug-B5mmo0ZX.js → Debug-CK-BLY-v.js} +1 -1
  3. package/dist/browser/{Demo-B2klxORi.js → Demo-B677YULI.js} +1 -1
  4. package/dist/browser/{Free-suULW-LU.js → Free-B_nU7Krr.js} +1 -1
  5. package/dist/browser/{GalleryContainer-BGBNGRKU.js → GalleryContainer-DcZrZnJz.js} +2 -2
  6. package/dist/browser/{GpsLoader-Idv0kq5D.js → GpsLoader-D9ghVrHk.js} +5 -5
  7. package/dist/browser/{KioskStore-Dg9jaX5d.js → KioskStore-BY2LVJPr.js} +4 -4
  8. package/dist/browser/{LayerStore-CK6wLW56.js → LayerStore-Cdwr6Hsw.js} +5 -5
  9. package/dist/browser/{MaplibreAdapter-uZUhZfFW.js → MaplibreAdapter-aWJl2IuA.js} +58 -59
  10. package/dist/browser/{ModalContainer-DWm8vEaI.js → ModalContainer-DnZxo0qA.js} +1 -1
  11. package/dist/browser/{RouteStore-NE2I9tiF.js → RouteStore-DTRRmaH_.js} +1552 -740
  12. package/dist/browser/{SetKioskMode-Dwlf5w7q.js → SetKioskMode-KMjCaliE.js} +2 -2
  13. package/dist/browser/{ShowKiosk-Cr-QmIUT.js → ShowKiosk-C_gEEGg7.js} +3 -3
  14. package/dist/browser/{ViewerMenuPanel-CTAjGsq2.js → ViewerMenuPanel-CbkSUP3L.js} +3 -3
  15. package/dist/browser/bundle.json +31 -34
  16. package/dist/browser/{components-BjEhhgf2.js → components-DRXsdUhs.js} +727 -727
  17. package/dist/browser/{create-live-plan-BaEGBhGA.js → create-live-plan-DnaL_dh7.js} +386 -725
  18. package/dist/browser/{floorplan.loader-CGzIMplb.js → floorplan.loader-151P9pJo.js} +6 -6
  19. package/dist/browser/{floorplan.ready-r96zV9bP.js → floorplan.ready-CCnzh5dy.js} +470 -378
  20. package/dist/browser/{i18n-BgFBhYOU.js → i18n-DRDvImjG.js} +7 -2
  21. package/dist/browser/index.js +8 -8
  22. package/dist/browser/{venue-public-BA3x-n4N.js → init-ui-DsRfN2rh.js} +8 -18
  23. package/dist/browser/{integrateKiosk-D45vYRsm.js → integrateKiosk-w_EetoNQ.js} +1 -1
  24. package/dist/browser/{is-debug-BRHdrnKr.js → is-debug-6YYr83sg.js} +2 -2
  25. package/dist/browser/{journey-plan-DtL28HMP.js → journey-plan-CEf1fFZz.js} +16 -16
  26. package/dist/browser/{kiosk-mode-DfkGlDkT.js → kiosk-mode-Ck1FQGr9.js} +2 -2
  27. package/dist/browser/{kioskUrlParam-CnYhnC_7.js → kioskUrlParam-BinDd3Gf.js} +1 -1
  28. package/dist/browser/{loadImage-DzSnRAxX.js → loadImage-CenmkrfL.js} +1 -1
  29. package/dist/browser/{logDeviceInfo-BTqyv9Xe.js → logDeviceInfo-OsKRXOu4.js} +4 -4
  30. package/dist/browser/{debounce-raMZ2DqK.js → venue-selection-DLUrexiA.js} +8 -18
  31. package/dist/browser/{viewport-B7plho3P.js → viewport-CBi835qx.js} +1 -1
  32. package/dist/esm/floorplan.ready.js +10 -0
  33. package/dist/esm/store/RouteStore.d.ts +10 -0
  34. package/dist/esm/store/RouteStore.js +48 -16
  35. package/dist/esm/store/VenueStore.d.ts +7 -0
  36. package/dist/esm/store/VenueStore.js +9 -0
  37. package/dist/esm/tools/sdk-telemetry.d.ts +10 -0
  38. package/dist/esm/tools/sdk-telemetry.js +122 -0
  39. package/dist/esm/tools/settings.js +1 -1
  40. package/package.json +10 -10
  41. package/dist/browser/venues-DKpIy-87.js +0 -447
@@ -0,0 +1,122 @@
1
+ import { peekConfig } from '@expofp/config';
2
+ import debug from 'debug';
3
+ /**
4
+ * SDK telemetry, sent while the `sdkTelemetry` flag is on to the intake the
5
+ * playbook's `development/sdk-telemetry.md` describes. The intake has no rate
6
+ * limit, so position batches go one request at a time, at least a second
7
+ * apart, and further apart while the intake keeps failing. An event the intake
8
+ * answered is never sent again, whatever the answer. Position items carry the
9
+ * `selectCurrentPosition` arguments as the host passed them, coordinates included.
10
+ */
11
+ const log = debug('efp:sdk-telemetry');
12
+ /** The last segment names this SDK as the source in Loki. */
13
+ const INTAKE_URL = 'https://sdk-telemetry.expofp.com/sdk-data/floorplan-sdk-web';
14
+ /** Public by nature in a browser: per the playbook it only keeps junk out. */
15
+ const INTAKE_TOKEN = 'KaptzDWTgJ_GXhb5Jg7ByTW0KK_poitr21X_-IcJeE4';
16
+ /** The localStorage queue of `selectCurrentPosition` calls; the expo ends the key. */
17
+ const POSITION_QUEUE_KEY = 'efp-sdk-telemetry-positions:';
18
+ /** The queue keeps the newest calls past this, which also holds a batch under the intake's 1 MiB. */
19
+ const MAX_QUEUED_POSITIONS = 3_000;
20
+ /** The least time between two position requests; each failure in a row doubles it, up to the max. */
21
+ const MIN_SEND_INTERVAL_MS = 1_000;
22
+ const MAX_SEND_INTERVAL_MS = 60_000;
23
+ /** A position send is scheduled or in flight: anything queued meanwhile goes with the next one. */
24
+ let positionSendBusy = false;
25
+ /** When the last position request started, by `performance.now()`. */
26
+ let lastPositionSendAt = -Infinity;
27
+ /** Position requests in a row the intake did not accept. */
28
+ let failedPositionSends = 0;
29
+ /** Sends one event while SDK telemetry is on. Never throws. */
30
+ export function sendSdkTelemetry(event) {
31
+ const config = enabledConfig();
32
+ if (config)
33
+ void post(config.expo, { event });
34
+ }
35
+ /**
36
+ * Queues one `selectCurrentPosition` call in localStorage, where it outlives
37
+ * the page, and sends the queue as one event once the previous request is done
38
+ * and the interval since it has passed. A batch that never reached the intake
39
+ * (offline, network error) stays queued for the next send.
40
+ */
41
+ export function queuePositionTelemetry(item) {
42
+ const config = enabledConfig();
43
+ if (!config)
44
+ return;
45
+ const key = POSITION_QUEUE_KEY + config.expo;
46
+ storeQueue(key, [...readQueue(key), { ts: new Date().toISOString(), ...item }]);
47
+ schedulePositionSend();
48
+ }
49
+ function schedulePositionSend() {
50
+ if (positionSendBusy)
51
+ return;
52
+ positionSendBusy = true;
53
+ const interval = Math.min(MIN_SEND_INTERVAL_MS * 2 ** failedPositionSends, MAX_SEND_INTERVAL_MS);
54
+ const wait = Math.max(0, lastPositionSendAt + interval - performance.now());
55
+ setTimeout(() => void sendPositionQueue(), wait);
56
+ }
57
+ async function sendPositionQueue() {
58
+ const config = enabledConfig();
59
+ const key = POSITION_QUEUE_KEY + (config?.expo ?? '');
60
+ const items = readQueue(key);
61
+ // offline, the queue stays as it is until a later call schedules a send
62
+ if (!config || items.length === 0 || navigator.onLine === false) {
63
+ positionSendBusy = false;
64
+ return;
65
+ }
66
+ storeQueue(key, []);
67
+ lastPositionSendAt = performance.now();
68
+ const status = await post(config.expo, { event: 'selectCurrentPosition', items });
69
+ // a batch that never reached the intake goes back, ahead of calls queued meanwhile
70
+ if (status === undefined)
71
+ storeQueue(key, [...items, ...readQueue(key)]);
72
+ failedPositionSends = status === 200 ? 0 : failedPositionSends + 1;
73
+ positionSendBusy = false;
74
+ if (readQueue(key).length > 0)
75
+ schedulePositionSend();
76
+ }
77
+ /** Resolves to the intake's HTTP status, or `undefined` when the request never reached it. */
78
+ async function post(expo, fields) {
79
+ try {
80
+ const response = await fetch(INTAKE_URL, {
81
+ method: 'POST',
82
+ headers: { Authorization: `Bearer ${INTAKE_TOKEN}`, 'Content-Type': 'application/json' },
83
+ body: JSON.stringify({
84
+ ts: new Date().toISOString(),
85
+ version: typeof __BUILD_INFO__ === 'undefined' ? undefined : __BUILD_INFO__.version,
86
+ expo,
87
+ ...fields,
88
+ }),
89
+ });
90
+ if (response.status !== 200) {
91
+ log('event refused', response.status, await response.text().catch(() => ''));
92
+ }
93
+ return response.status;
94
+ }
95
+ catch (error) {
96
+ log('event not sent', error);
97
+ return undefined;
98
+ }
99
+ }
100
+ function readQueue(key) {
101
+ try {
102
+ return JSON.parse(localStorage.getItem(key) ?? '[]');
103
+ }
104
+ catch {
105
+ return [];
106
+ }
107
+ }
108
+ function storeQueue(key, items) {
109
+ try {
110
+ if (items.length === 0)
111
+ localStorage.removeItem(key);
112
+ else
113
+ localStorage.setItem(key, JSON.stringify(items.slice(-MAX_QUEUED_POSITIONS)));
114
+ }
115
+ catch (error) {
116
+ log('position queue not stored', error);
117
+ }
118
+ }
119
+ function enabledConfig() {
120
+ const config = peekConfig();
121
+ return config?.sdkTelemetry === true ? config : undefined;
122
+ }
@@ -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.2d6c681",
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.2d6c681",
73
- "@expofp/debug": "0.0.0-experimental.2d6c681",
74
- "@expofp/geometry": "0.0.0-experimental.2d6c681",
75
- "@expofp/renderer": "0.0.0-experimental.2d6c681",
76
- "@expofp/resolve": "0.0.0-experimental.2d6c681",
77
- "@expofp/schema": "0.0.0-experimental.2d6c681",
78
- "@expofp/ui": "0.0.0-experimental.2d6c681",
79
- "@expofp/utils": "0.0.0-experimental.2d6c681",
80
- "@expofp/wayfinding": "0.0.0-experimental.2d6c681"
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-CK6wLW56.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 };