@minmaps-dev/mm-web-sdk 1.0.0-rc.3 → 1.0.0-rc.4

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.
package/README.md CHANGED
@@ -1,31 +1,77 @@
1
+ <div align="center">
2
+
1
3
  # MinuteMaps Web SDK
2
4
 
3
- `@minmaps-dev/mm-web-sdk` is the official MinuteMaps SDK for the web. It renders indoor venues — floors, POIs, amenities, destinations, and wayfinding routes — on top of [MapLibre GL JS](https://maplibre.org/), with data sourced from JACS.
5
+ **Render indoor venues — floors, POIs, amenities, destinations, and wayfinding routes — on top of [MapLibre GL JS](https://maplibre.org/).**
4
6
 
5
- ## Features
7
+ [![npm](https://img.shields.io/npm/v/@minmaps-dev/mm-web-sdk?label=npm)](https://www.npmjs.com/package/@minmaps-dev/mm-web-sdk)
8
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
9
+ [![types](https://img.shields.io/badge/types-included-blue)](./dist/index.d.ts)
6
10
 
7
- - **Venue + floors** — load a venue by `customerId` / `venueId`, switch active floor, and let the SDK manage layer visibility.
8
- - **POIs, amenities, destinations** — query the venue, filter by floor, and run keyword searches.
9
- - **Wayfinding** — compute kiosk-to-destination or waypoint-to-waypoint routes and render them on the map.
10
- - **View modes** — toggle 3D, flat (top-down), and 2D-units modes at runtime.
11
- - **Camera control** — `setView` / `resetView` / `getCameraPosition`, plus a live `cameraChange` event for compass UIs.
12
- - **React entrypoint** — drop-in `<MinuteMapsView />` for React 18/19 apps.
13
- - **JACS proxy or direct mode** — keep credentials server-side with the proxy mode, or call JACS directly from trusted environments.
11
+ </div>
14
12
 
15
- ## Installation
13
+ `@minmaps-dev/mm-web-sdk` is the official MinuteMaps SDK for the web. It loads venues from JACS, manages floors, POIs, amenities, destinations, and the camera, and gives you a small, well-typed surface for building modern kiosks and indoor mapping web apps.
16
14
 
17
15
  ```bash
18
16
  npm install @minmaps-dev/mm-web-sdk maplibre-gl @turf/turf
19
17
  ```
20
18
 
21
- `maplibre-gl` (v4) and `@turf/turf` (v7) are peer dependencies. `react` / `react-dom` (v18 or v19) are optional peers, only required if you use the `/react` entrypoint.
22
-
23
- Don't forget to import the MapLibre stylesheet once in your app:
24
-
25
19
  ```ts
20
+ import { MinuteMaps } from '@minmaps-dev/mm-web-sdk'
26
21
  import 'maplibre-gl/dist/maplibre-gl.css'
22
+
23
+ const sdk = new MinuteMaps({
24
+ container: 'map',
25
+ jmap: { host: '', customerId: 123, venueId: 456 },
26
+ jacs: { mode: 'proxy', proxyBaseUrl: '/api/jacs' },
27
+ options: { styleMode: 'sdkTemplate' },
28
+ })
29
+
30
+ sdk.on('ready', ({ venue }) => console.log('venue ready', venue?.name))
31
+ await sdk.init()
27
32
  ```
28
33
 
34
+ ---
35
+
36
+ ## Status
37
+
38
+ This SDK is on a pre-1.0 release candidate (`1.0.0-rc.3`). The following capabilities are wired but **dormant pending backend support** — they are not yet functional in the published build:
39
+
40
+ | Area | Status | Notes |
41
+ | --- | --- | --- |
42
+ | Floors, POIs, amenities, destinations | ✅ Shipped | Loads via JACS `building/full` + `venue/full`. |
43
+ | Camera + view modes (3D/2D/flat) | ✅ Shipped | Style toggles work against the bundled `alt3-hybrid-style.json`. |
44
+ | Venue-served stylesheets | 🚧 Roadmap | SDK currently uses its bundled style; `loadAndPatchVenueStyle()` is bypassed. |
45
+ | Polygon layers + 3D map templates | 🚧 Roadmap | `buildPolygonLayers` / `applyMapTemplate3d` imports are commented in `src/sdk.ts`. |
46
+ | Wayfinding | 🚧 Roadmap | Route renderer is fully built, but the runtime provider is a stub that throws *"Wayfinding is not yet implemented in the SDK"*. |
47
+
48
+ Track re-enable points by grepping `// TODO: Re-enable` in `src/sdk.ts` and `src/data/jacsDataProvider.ts`.
49
+
50
+ ---
51
+
52
+ ## What's in the box
53
+
54
+ - **Venue + floors** — load a venue by `customerId` / `venueId`, switch active floor, let the SDK manage layer visibility.
55
+ - **POIs, amenities, destinations** — query by floor, run keyword searches, find the kiosk's "You are here" location.
56
+ - **View modes** — toggle 3D extrusion, flat (top-down), and 2D-units modes at runtime.
57
+ - **Camera control** — `setView` / `resetView` / `getCameraPosition`, plus a live `cameraChange` event for compass UIs.
58
+ - **React entrypoint** — drop-in `<MinuteMapsView />` for React 18/19.
59
+ - **JACS proxy or direct mode** — keep credentials server-side (recommended) or call JACS directly from trusted environments.
60
+
61
+ ---
62
+
63
+ ## Documentation
64
+
65
+ The lean root README intentionally stops here. For depth, see:
66
+
67
+ - [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) — module map, init flow, JACS data path, style patching, dormant 3D notes.
68
+ - [`docs/API.md`](./docs/API.md) — full public API surface grouped by lifecycle, floors, POIs, amenities, wayfinding, camera, events.
69
+ - [`docs/KIOSK.md`](./docs/KIOSK.md) — kiosk integration patterns (You-Are-Here, kiosk-to-destination wayfinding once enabled, view-mode UX, sprite hosting, idle reset).
70
+
71
+ External integrators will usually only need the [API](./docs/API.md) and [Kiosk](./docs/KIOSK.md) docs. Internal MTS engineers should also read [Architecture](./docs/ARCHITECTURE.md) before touching `src/sdk.ts` or the JACS provider.
72
+
73
+ ---
74
+
29
75
  ## Quick start (vanilla)
30
76
 
31
77
  ```ts
@@ -51,9 +97,8 @@ const sdk = new MinuteMaps({
51
97
  },
52
98
  })
53
99
 
54
- sdk.on('ready', ({ venue }) => {
55
- console.log('venue ready', venue?.name)
56
- })
100
+ sdk.on('ready', ({ venue }) => console.log('venue ready', venue?.name))
101
+ sdk.on('floorChanged', ({ floor }) => console.log('now showing', floor?.name))
57
102
 
58
103
  await sdk.init()
59
104
  ```
@@ -79,9 +124,11 @@ export function Map() {
79
124
  }
80
125
  ```
81
126
 
82
- For a more involved integration that wires events, floors, search, and wayfinding into React state, see the [`mm-web-sdk-example`](../mm-web-sdk-example) Next.js app particularly [`hooks/useMap.ts`](../mm-web-sdk-example/hooks/useMap.ts).
127
+ The React entry is intentionally minimal: it owns its own `<div>`, calls `init()` on mount, and `destroy()` on unmount. Reach for the vanilla `MinuteMaps` class when you need imperative control (floor switching from a side panel, camera animations driven by Redux, etc.).
128
+
129
+ ---
83
130
 
84
- ## Configuration
131
+ ## Configuration at a glance
85
132
 
86
133
  ```ts
87
134
  type SDKConfig = {
@@ -95,37 +142,29 @@ type SDKConfig = {
95
142
  }
96
143
  jacs: {
97
144
  mode: 'proxy' | 'direct'
98
- host?: string // 'direct' only
145
+ host?: string // 'direct' only
99
146
  auth?: { clientId: string; username: string; password: string } // 'direct' only
100
147
  proxyBaseUrl?: string // default '/api/jacs'
101
148
  }
102
149
  options?: SDKOptions
103
150
  }
104
-
105
- type SDKOptions = {
106
- debug?: boolean
107
- initialFloor?: string | number
108
- customSprite?: string // sprite URL prefix (no extension)
109
- minIndoorZoom?: number
110
- boundsPadding?: number // default 50
111
- styleMode?: 'venueStyleUrl' | 'sdkTemplate'
112
- templateOverrideMode?: 'colorsOnly' | 'colorsAndConstants' | 'all'
113
- }
114
151
  ```
115
152
 
153
+ Full option reference and an annotated `SDKOptions` shape live in [`docs/API.md`](./docs/API.md#configuration).
154
+
116
155
  ### JACS proxy mode (recommended)
117
156
 
118
- Browser apps should use `mode: 'proxy'` and forward requests through your own server so JACS credentials never reach the client. The example app ships a Next.js route handler at [`app/api/jacs/[...path]/route.ts`](../mm-web-sdk-example/app/api/jacs/%5B...path%5D/route.ts) that:
157
+ Browser apps should use `mode: 'proxy'` and forward requests through your own server so JACS credentials never reach the client. Your proxy should:
119
158
 
120
- 1. Reads `JACS_HOST`, `JACS_CLIENT_ID`, `JACS_USERNAME`, `JACS_PASSWORD` from server env.
121
- 2. Exchanges the password grant for a bearer token (cached until expiry).
122
- 3. Forwards `GET /api/jacs/<path>` to `${JACS_HOST}/JACS/api/<path>` with the token attached.
159
+ 1. Read `JACS_HOST`, `JACS_CLIENT_ID`, `JACS_USERNAME`, `JACS_PASSWORD` from server env.
160
+ 2. Exchange the password grant for a bearer token (cache until expiry).
161
+ 3. Forward `GET /api/jacs/<path>` to `${JACS_HOST}/JACS/api/<path>` with the token attached.
123
162
 
124
- Copy that handler into your own backend (or adapt it to your framework) and point `jacs.proxyBaseUrl` at it.
163
+ A reference Next.js route handler ships in the example app at `mm-web-sdk-example/app/api/jacs/[...path]/route.ts`. Copy it into your own backend or adapt it to your framework, then point `jacs.proxyBaseUrl` at it.
125
164
 
126
165
  ### JACS direct mode
127
166
 
128
- For trusted environments (server-rendered pages, Electron kiosks, internal tools) you can call JACS directly:
167
+ For trusted environments server-rendered pages, Electron kiosks, internal tools call JACS directly:
129
168
 
130
169
  ```ts
131
170
  jacs: {
@@ -135,104 +174,53 @@ jacs: {
135
174
  }
136
175
  ```
137
176
 
138
- ## API
177
+ > ⚠ Never ship `direct` mode to a public browser bundle. Your JACS credentials would be visible to anyone with devtools.
139
178
 
140
- ### Class `MinuteMaps`
179
+ ---
141
180
 
142
- ```ts
143
- new MinuteMaps(config: SDKConfig)
144
- sdk.init(): Promise<void>
145
- sdk.destroy(): void
146
- sdk.isReady(): boolean
147
- sdk.getMap(): maplibregl.Map | null
148
- ```
149
-
150
- `createMinuteMapsSDK(config)` is a factory shorthand for `new MinuteMaps(config)`.
151
-
152
- ### Floors
153
-
154
- ```ts
155
- sdk.getFloors(): Floor[]
156
- sdk.getCurrentFloor(): Floor | null
157
- sdk.getDefaultFloor(): Floor | null
158
- sdk.setCurrentFloor(floor: Floor): Promise<void>
159
- ```
160
-
161
- ### POIs, destinations, search
162
-
163
- ```ts
164
- sdk.getAllPOIs(floor?: Floor): POI[]
165
- sdk.getDestinations(floor?: Floor): Destination[]
166
- sdk.searchPOIs(query: string, floor?: Floor): POI[]
167
- sdk.getYouAreHerePOI(floor?: Floor): POI | null
168
- sdk.getYouAreHereCoordinates(floor?: Floor): [number, number] | null
169
- ```
170
-
171
- ### Amenities (`sdk.amenities`)
172
-
173
- ```ts
174
- sdk.amenities.getAll(): AmenityWithFloor[]
175
- sdk.amenities.getByFloorId(floorId): AmenityWithFloor[]
176
- sdk.amenities.getAllKiosks(): AmenityWithFloor[]
177
- sdk.amenities.getKioskForFloor(floorId): AmenityWithFloor | null
178
- ```
179
-
180
- ### Wayfinding
181
+ ## Sprites
181
182
 
182
- ```ts
183
- sdk.navigateFromKioskToDestination(destination): Promise<...>
184
- sdk.wayfindBetweenWaypoints(from, to, opts?: {
185
- centerMode?: 'none' | 'destination' | 'route'
186
- zoom?: number
187
- }): Promise<...>
188
- sdk.clearRoute(): void
189
- ```
183
+ `options.customSprite` is a sprite URL **prefix without extension** — MapLibre appends `.json` and `.png` (and `@2x` variants) automatically. The example app serves its sprite from `mm-web-sdk-example/public/sprites/`.
190
184
 
191
- ### Camera + view modes
185
+ ---
192
186
 
193
- ```ts
194
- sdk.setView({ center?, zoom?, pitch?, bearing?, animate?, duration? })
195
- sdk.resetView({ animate?, duration? })
196
- sdk.getCameraPosition(): CameraState | null
187
+ ## Development
197
188
 
198
- sdk.set3dEnabled(enabled) / toggle3d() / getIs3dEnabled()
199
- sdk.setUnits2dEnabled(enabled) / toggleUnits2d() / getIsUnits2dEnabled()
200
- sdk.setFlatMode(enabled) / toggleFlatMode() / getIsFlatMode()
189
+ ```bash
190
+ npm install
191
+ npm run dev:sdk # rollup --watch (rebuilds dist/ on change)
192
+ npm run build # rimraf dist + production rollup build
193
+ npm run typecheck # tsc --noEmit
194
+ npm test # vitest run
195
+ npm run test:watch # vitest in watch mode
196
+ npm run test:coverage # vitest run --coverage (v8 provider)
201
197
  ```
202
198
 
203
- ### MapLibre passthroughs
199
+ The build emits ESM, CJS, and types under `dist/` for both the root entry and the `/react` entry. Tests live in `tests/` and target the three highest-leverage modules: `JacsProvider`, `WayfindingManager`, and `ViewModeController`. Coverage thresholds are gated in `vitest.config.ts` (currently 60% lines/funcs/stmts, 50% branches).
204
200
 
205
- ```ts
206
- sdk.addControl(control, position?) // forwards to the underlying MapLibre map
207
- sdk.getMap() // escape hatch: the raw maplibregl.Map
208
- ```
201
+ ### Continuous integration
209
202
 
210
- ### Events
203
+ Two workflows in `.github/workflows/`:
211
204
 
212
- Subscribe with `sdk.on(event, cb)` / unsubscribe with `sdk.off(event, cb)`.
205
+ - **`ci.yml`** — runs typecheck, vitest with coverage, and the production build on every push and pull request to `main` / `dev`. Coverage and `dist/` are uploaded as artifacts.
206
+ - **`publish.yml`** — runs on tags matching `v*` (or via manual dispatch). Verifies the tag matches `package.json` version, runs the full pipeline, and publishes to npm with provenance. Requires an `NPM_TOKEN` repo secret.
213
207
 
214
- | Event | Payload | When |
215
- | --------------- | ----------------------------- | ---------------------------------------------------------- |
216
- | `ready` | `{ venue }` | Map loaded and the initial floor is rendered. |
217
- | `floorsLoaded` | `{}` | All floor geojson is available. |
218
- | `floorChanged` | `{ floor }` | After `setCurrentFloor` resolves. |
219
- | `cameraChange` | `{ camera: CameraState }` | On every map `move` (drives compass/heading UI). |
220
- | `error` | `{ error }` | Init or runtime error. |
208
+ > **Internal note:** future Claude sessions get oriented from [`CLAUDE.md`](./CLAUDE.md). Repo-local subagents in [`.claude/agents/`](./.claude/agents/) cover API doc sync, release notes, and style/template edits.
221
209
 
222
- ## Sprites
210
+ ---
223
211
 
224
- Pass `options.customSprite` as a sprite URL prefix without the extension (MapLibre will append `.json` and `.png` / `@2x`). The example app serves its sprite from [`public/sprites/`](../mm-web-sdk-example/public/sprites/).
212
+ ## Browser + framework support
225
213
 
226
- ## Development
214
+ | Target | Version |
215
+ | --- | --- |
216
+ | Node (build/dev) | ≥ 18 |
217
+ | `maplibre-gl` | ^4 |
218
+ | `@turf/turf` | ^7 |
219
+ | `react` / `react-dom` | ^18 or ^19 (only required for `/react` entry) |
227
220
 
228
- ```bash
229
- npm install
230
- npm run dev:sdk # rollup --watch
231
- npm run build # clean + production build
232
- npm run typecheck # tsc --noEmit
233
- ```
221
+ Modern evergreen browsers. Kiosk targets are typically pinned Chromium builds — if you need to support a specific minimum, open an issue.
234
222
 
235
- The build emits ESM, CJS, and types under `dist/` for both the root entry and the `/react` entry.
223
+ ---
236
224
 
237
225
  ## License
238
226
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var t=require("maplibre-gl");function e(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(o){if("default"!==o){var i=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(e,o,i.get?i:{enumerable:!0,get:function(){return t[o]}})}}),e.default=t,Object.freeze(e)}var o=e(require("@turf/turf"));const i={ensureGeoJson(t,e){t.getSource(e)||t.addSource(e,{type:"geojson",data:{type:"FeatureCollection",features:[]}})},setData(t,e,o){const i=t.getSource(e);i?.setData?.(o)}},n="indoor-data",r="poi-data",s="unit-walls",a="route-data",l=["boundary-fill","boundary-outline","units-fill","units-wall-extrusion","units-wall-custom-extrusion","corridors-fill","corridors-outline","building-extrusion"],u=()=>{};function c(t){const e=Boolean(t?.enabled),o=function(t){const e=String(t||"").trim();return e?`[${e}]`:""}(t?.prefix||"MinuteMapsSDK");return e?{debug:(...t)=>console.debug(o,...t),log:(...t)=>console.log(o,...t),warn:(...t)=>console.warn(o,...t),error:(...t)=>console.error(o,...t)}:{debug:u,log:u,warn:u,error:u}}c({enabled:!0,prefix:"MinuteMapsSDK"});const d={applyFloor(t,e,o=1){d.updateWalls(t,e,o),d.updateIndoor(t,e)},updateIndoor(t,e){i.setData(t,n,e.geojson);try{const t=e?.geojson?.features||[],o={};for(const e of t){const t=e?.properties?.featureType,i=null==t?"(missing)":String(t);o[i]=(o[i]||0)+1}Object.entries(o).sort((t,e)=>e[1]-t[1]).slice(0,15)}catch{}},updateWalls(t,e,n=1){const r=function(t,e=1){const i=(t.features||[]).filter(t=>"Units"===t.properties?.featureType).map(t=>{try{const i=o.buffer(t,-e,{units:"feet"});if(!i)return null;const n={...t.properties,featureType:"UnitWalls"};if(null==n.custom_height){const t=n.customProperties?.custom_height??n.custom_height??n.height??n.wall_height,e="number"==typeof t?t:Number(t);Number.isFinite(e)&&(n.custom_height=e)}return{type:"Feature",geometry:{type:"Polygon",coordinates:[t.geometry.coordinates[0],i.geometry.coordinates[0]]},properties:n}}catch{return null}}).filter(Boolean);return{type:"FeatureCollection",features:i}}(e.geojson,n);i.setData(t,s,r)},boundsFromGeoJson(t){try{const[e,i,n,r]=o.bbox(t),s=Math.min(e,n),a=Math.max(e,n),l=Math.min(i,r);return[[s,l],[a,Math.max(i,r)]]}catch{return null}},selectDefaultFloor:t=>Array.isArray(t)&&0!==t.length&&(t.find(t=>t.isDefault)||t[0])||null,selectInitialFloor(t,e){if(!Array.isArray(t)||0===t.length)return null;if(null!=e){const o=t.find(t=>t.id===e);if(o)return o}return d.selectDefaultFloor(t)},async activateFloor(t,e,o){if(!t)throw new Error("activateFloor requires an initialized map");if(e?.geojson&&d.applyFloor(t,e,o.wallFeet),await o.updatePOIs(e),!e?.geojson)return void(t.getZoom()<o.minIndoorZoom&&t.setZoom(o.minIndoorZoom));const i=d.boundsFromGeoJson(e.geojson);if(!i)return;const n=!o.didFit;let r=n;if(!r){const[[e,o],[n,s]]=i,a=t.getBounds();r=a.getWest()>n||a.getEast()<e||a.getSouth()>s||a.getNorth()<o}r?(t.fitBounds(i,{padding:o.boundsPadding,animate:!n,duration:700,bearing:t.getBearing(),pitch:t.getPitch()}),t.once("moveend",()=>{t.getZoom()<o.minIndoorZoom&&t.setZoom(o.minIndoorZoom)}),o.setDidFit(!0),o.log?.("camera :: fitToFloor",{floorId:e.id,animated:!n})):(t.getZoom()<o.minIndoorZoom&&t.setZoom(o.minIndoorZoom),o.log?.("camera :: fit skipped (floor overlaps viewport)",{floorId:e.id}))}};class p{floors=[];currentFloor=null;didFit=!1;getMap;getConfig;updatePoiSource;logFn;constructor(t){this.getMap=t.getMap,this.getConfig=t.getConfig,this.updatePoiSource=t.updatePoiSource,this.logFn=t.log}log(...t){this.logFn&&this.logFn(...t)}setFloors(t){this.floors=t}getFloors(){return[...this.floors]}getCurrentFloor(){return this.currentFloor}setDidFit(t){this.didFit=t}getDefaultFloor(){return d.selectDefaultFloor(this.floors)}getInitialFloor(){const t=this.getConfig();return d.selectInitialFloor(this.floors,t.options?.initialFloor)}async setCurrentFloor(t){const e=this.getMap();if(!e)throw new Error("Map is not initialized");this.currentFloor=t,this.log("floor :: setCurrentFloor",{id:t.id,name:t.name,geojsonFeatures:t.geojson?.features?.length??0});const o=this.getConfig(),i=o.options?.wallThickness??1,n=o.options?.boundsPadding??50,r=o.options?.minIndoorZoom??16.5;await d.activateFloor(e,t,{wallFeet:i,updatePOIs:t=>this.updatePoiSource(t),didFit:this.didFit,setDidFit:t=>{this.didFit=t},boundsPadding:n,minIndoorZoom:r,log:(t,e)=>this.log(t,e)})}}const f=c({enabled:!0,prefix:"MinuteMapsSDK"}),g=new Map,h={async getSpriteKeys(t){const e=function(t){if(!t)return;if("string"==typeof t)return t;if(Array.isArray(t)){const e=t[0];if(e&&"string"==typeof e.url)return e.url}if("object"==typeof t&&null!==t){const e=t?.url;if("string"==typeof e)return e}return}(t?.getStyle?.()?.sprite);if(!e||"function"!=typeof fetch)return new Set;const o=e.endsWith(".json")?e:`${e}.json`;if(g.has(o))return g.get(o);try{const t=await fetch(o);if(!t.ok)throw new Error(`Failed to load sprite JSON (${t.status})`);const e=await t.json(),i=new Set(Object.keys(e||{}));return g.set(o,i),i}catch(t){f.warn("sprite fetch failed",o,t);const e=new Set;return g.set(o,e),e}}};const y="units-outline-2d",m=["units-wall-extrusion","units-wall-custom-extrusion"];class w{getMap;is3dEnabled=!0;isUnits2dEnabled=!1;isFlatMode=!1;cachedExtrusionIds=null;extrusionOriginalVisibility=null;unitsExtrusionOriginalVisibility=null;unitsOutlineOriginalVisibility=null;constructor(t){this.getMap=t}onStyleData(){if(this.map){if(this.cachedExtrusionIds=null,!this.is3dEnabled){const t=this.listExtrusionLayerIds();this.setLayersVisibility(t,"none")}this.isUnits2dEnabled&&this.applyUnits2dVisibility(!0)}}set3dEnabled(t){const e=this.map;if(!e)return;const o=this.listExtrusionLayerIds();if(this.cachedExtrusionIds=o,!this.extrusionOriginalVisibility){const t={};o.forEach(o=>{try{const i=e.getLayoutProperty(o,"visibility")||"visible";t[o]=i}catch{t[o]="visible"}}),this.extrusionOriginalVisibility=t}if(t){const t=this.extrusionOriginalVisibility||{};o.forEach(o=>{const i=t[o]??"visible";try{e.getLayer(o)&&e.setLayoutProperty(o,"visibility",i)}catch{}})}else this.setLayersVisibility(o,"none");this.is3dEnabled=t,e.triggerRepaint()}toggle3d(){this.set3dEnabled(!this.is3dEnabled)}getIs3dEnabled(){return this.is3dEnabled}setUnits2dEnabled(t){const e=this.map;e&&(this.applyUnits2dVisibility(t),this.isUnits2dEnabled=t,e.triggerRepaint())}toggleUnits2d(){this.setUnits2dEnabled(!this.isUnits2dEnabled)}getIsUnits2dEnabled(){return this.isUnits2dEnabled}setFlatMode(t){this.map&&(t?(this.set3dEnabled(!1),this.setUnits2dEnabled(!0)):(this.setUnits2dEnabled(!1),this.set3dEnabled(!0)),this.isFlatMode=t)}toggleFlatMode(){this.setFlatMode(!this.isFlatMode)}getIsFlatMode(){return this.isFlatMode}applyUnits2dVisibility(t){const e=this.map;if(e){if(!this.unitsExtrusionOriginalVisibility){const t={};m.forEach(o=>{try{const i=e.getLayoutProperty(o,"visibility")||"visible";t[o]=i}catch{t[o]="visible"}}),this.unitsExtrusionOriginalVisibility=t}if(null==this.unitsOutlineOriginalVisibility)try{const t=e.getLayoutProperty(y,"visibility");this.unitsOutlineOriginalVisibility=t??"none"}catch{this.unitsOutlineOriginalVisibility="none"}if(e.getLayer(y)){const o=t?"visible":this.unitsOutlineOriginalVisibility??"none";try{e.setLayoutProperty(y,"visibility",o)}catch{}}if(t)m.forEach(t=>{if(e.getLayer(t))try{e.setLayoutProperty(t,"visibility","none")}catch{}});else{const t=this.unitsExtrusionOriginalVisibility||{};m.forEach(o=>{const i=t[o]??"visible";if(e.getLayer(o))try{e.setLayoutProperty(o,"visibility",i)}catch{}})}}}listExtrusionLayerIds(){const t=this.map;if(!t)return[];try{const e=t.getStyle(),o=e?.layers||[],i=o.filter(t=>"fill-extrusion"===t?.type).map(t=>t.id),n=Array.isArray(l)?l:[],r=[];return n.forEach(t=>{const e=o.find(e=>e.id===t);e&&"fill-extrusion"===e.type&&r.push(t)}),[...new Set([...i,...r])]}catch{return this.cachedExtrusionIds||[]}}setLayersVisibility(t,e){const o=this.map;o&&t.forEach(t=>{try{o.getLayer(t)&&o.setLayoutProperty(t,"visibility",e)}catch{}})}get map(){return this.getMap()}}function b(t){if(!t)return null;const e=t.getCenter(),o=(t,e=6)=>function(t,e=6){const o=Number(t.toFixed(e));return Object.is(o,-0)?0:o}(t,e);return{center:[o(e.lng),o(e.lat)],zoom:o(t.getZoom(),4),pitch:o(t.getPitch(),2),bearing:o(t.getBearing(),2)}}const F={async updatePOIs(t,e,o){const[n,s]=await Promise.all([o.getAmenities(e.id),o.getDestinations(e.id)]),a=F.buildPOIs(e,n,s,o.spriteKeys);i.setData(t,r,F.toFeatureCollection(a))},buildPOIs(t,e=[],o=[],i){const n=t?.id;if(!n)return[];const r=[];let s=!1;for(const o of e||[]){if(!o.waypoints)continue;const e=A(o),a=v(o.svg,i)||void 0,l="you-are-here";for(const i of o.waypoints||[]){if(i.mapId!==n||!I(i.coordinates))continue;const[u,c]=i.coordinates,d=e&&!s,p=d?l:a,f=i.id??i._?.id;r.push({id:o.id,type:"amenity",name:d?"You are here":o.name||"Amenity",coordinates:[u,c],iconId:p,floorId:t.id,amenityType:o.type,keywords:o.keywords||[],showLabel:!0,isYouAreHere:d,waypointId:f,waypoint:i}),d&&(s=!0)}}for(const e of o||[])if(e.waypoints)for(const o of e.waypoints||[]){if(o.mapId!==n||!I(o.coordinates))continue;const[i,s]=o.coordinates,a=o.id??o._?.id;r.push({id:e.id,type:"destination",name:e.name||"Destination",coordinates:[i,s],floorId:t.id,showLabel:!0,waypointId:a,waypoint:o})}return r},toFeatureCollection:t=>({type:"FeatureCollection",features:t.map(t=>({type:"Feature",geometry:{type:"Point",coordinates:t.coordinates},properties:{id:t.id,name:t.name,poiType:t.type,iconId:t.iconId,floorId:t.floorId,keywords:t.keywords,amenityType:t.amenityType,showLabel:!1!==t.showLabel,isYouAreHere:!0===t.isYouAreHere}}))})};function x(t){return t.find(t=>t.isYouAreHere)||null}function I(t){return Array.isArray(t)&&t.length>=2}function v(t,e){if(!t||!e)return null;const o=/<svg[^>]*\bid\s*=\s*["']([^"']+)["']/i.exec(t),i=o?.[1];return i&&e.has(i)?i:null}function A(t){const e=t=>(t??"").toLowerCase(),o=e(t.name),i=(t.keywords||[]).map(t=>e(t)),n=t.extensors||{},r=e(n.type),s="kiosk"===o||o.includes("kiosk"),a=i.some(t=>t.includes("kiosk"));return s||a||"assistance"===r}class C{deps;routeAnimationFrame=null;routeAnimationStart=null;routeAnimationDurationMs=1200;routeActive=!1;constructor(t){this.deps=t}buildWayfindFeatureCollection(t){if(!t)return this.deps.warn?.("wayfind :: no result"),null;const e=[],o=t=>{if(!t)return;const o=t.coordinates||t.xyz||t._?.coordinates;if(Array.isArray(o)&&o.length>=2){const t=Number(o[0]),i=Number(o[1]);Number.isFinite(t)&&Number.isFinite(i)&&e.push([t,i])}};return Array.isArray(t)?t.length>0&&Array.isArray(t[0]?.points)?t[0].points.forEach(o):t.forEach(o):Array.isArray(t.points)?t.points.forEach(o):Array.isArray(t.path)?t.path.forEach(o):Array.isArray(t.paths?.[0]?.points)&&t.paths[0].points.forEach(o),e.length<2?(this.deps.warn?.("wayfind :: not enough coordinates to draw a route",{resultShape:{isArray:Array.isArray(t),hasPoints:Array.isArray(t.points),hasPath:Array.isArray(t.path),hasPaths0Points:Array.isArray(t.paths?.[0]?.points)},extractedCount:e.length}),null):(this.deps.log?.("wayfind :: extracted coordinates for route",{count:e.length,first:e[0],last:e[e.length-1]}),{type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"LineString",coordinates:e},properties:{}}]})}async wayfindBetweenWaypoints(t,e,o){const n=this.deps.getMap();if(!this.deps.getVenue()||!n)return this.deps.warn?.("wayfindBetweenWaypoints :: venue or map not ready"),null;let r=null;try{r=await this.deps.computeRoute(t,e)}catch(t){return this.deps.warn?.("wayfind :: computeRoute failed",t),null}this.deps.log?.("wayfind :: result",r);const s=this.buildWayfindFeatureCollection(r);if(!s)return r;i.setData(n,a,s),this.deps.log?.("wayfind :: route source updated",{featureCount:s.features.length}),this.startRouteAnimation();const l=o?.centerMode??"route",u=o?.zoom??19;if("none"!==l){const t=s.features[0]?.geometry;if(t&&"LineString"===t.type&&Array.isArray(t.coordinates)){const e=t.coordinates;if("destination"===l){const t=e[e.length-1];n.flyTo({center:t,zoom:u,pitch:45,bearing:0,animate:!0,duration:900})}else if("route"===l){const t=e.map(t=>t[0]),o=e.map(t=>t[1]),i=Math.min(...t),r=Math.max(...t),s=[[i,Math.min(...o)],[r,Math.max(...o)]];n.fitBounds(s,{padding:this.deps.getBoundsPadding(),animate:!0})}}}return r}async navigateFromKioskToDestination(t){const e=this.deps.getMap(),o=this.deps.getVenue();if(!e||!o)return null;const i=this.deps.getYouAreHerePOI();if(!i||!i.waypoint)return this.deps.warn?.("navigateFromKioskToDestination :: no you-are-here waypoint available",i),null;const n=t.waypoint||t.waypoints?.[0];if(!n)return this.deps.warn?.("navigateFromKioskToDestination :: destination has no waypoint",t),null;this.deps.log?.("navigateFromKioskToDestination :: from kiosk to destination",{kioskWaypoint:i.waypoint,destWaypoint:n});const r=this.deps.getYouAreHereCoordinates()??i.waypoint?.coordinates,s=n.coordinates||n.xyz||n._?.coordinates,a=Array.isArray(s)&&s.length>=2?[Number(s[0]),Number(s[1])]:null;return r&&a?this.showRouteContext(r,a):this.deps.warn?.("navigateFromKioskToDestination :: could not derive endpoint coordinates",{fromCoords:r,rawDest:s}),this.wayfindBetweenWaypoints(i.waypoint,n,{centerMode:"route"})}clearRoute(){const t=this.deps.getMap();if(!t)return;this.stopRouteAnimation();i.setData(t,a,{type:"FeatureCollection",features:[]}),this.deps.log?.("wayfind :: route cleared")}setPoiLayersVisible(t){const e=this.deps.getMap();if(!e)return;const o=t?"visible":"none";["poi-accessibility-icons","poi-destination-circles","poi-destination-labels","poi-entrance-exit-icons","poi-parking-icons","poi-other-amenity-icons"].forEach(t=>{e.getLayer(t)&&e.setLayoutProperty(t,"visibility",o)})}updateRouteEndpoints(t,e){const o=this.deps.getMap();if(!o)return;const i=o.getSource("route-endpoints");if(!i)return;const n={type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"Point",coordinates:t},properties:{role:"source"}},{type:"Feature",geometry:{type:"Point",coordinates:e},properties:{role:"destination"}}]};i.setData(n)}clearRouteEndpoints(){const t=this.deps.getMap();if(!t)return;const e=t.getSource("route-endpoints");if(!e)return;e.setData({type:"FeatureCollection",features:[]})}showRouteContext(t,e){this.updateRouteEndpoints(t,e)}hideRouteContext(){this.setPoiLayersVisible(!0),this.clearRouteEndpoints()}startRouteAnimation(){if(!this.deps.getMap())return;if("undefined"==typeof window)return;null!=this.routeAnimationFrame&&(cancelAnimationFrame(this.routeAnimationFrame),this.routeAnimationFrame=null),this.routeAnimationStart=performance.now(),this.routeActive=!0;const t=this.deps.debug,e=o=>{const i=this.deps.getMap();if(!i||!this.routeActive||null==this.routeAnimationStart)return;const n=o-this.routeAnimationStart,r=Math.min(1,n/this.routeAnimationDurationMs),s=Math.max(.001,r);t&&this.deps.log?.("route animation frame",{t:r,clamped:s});const a=Math.max(0,s-.01),l=Math.min(1,s+.01),u=["interpolate",["linear"],["line-progress"],0,"rgba(0,122,255,1.0)",a,"rgba(0,122,255,1.0)",l,"rgba(0,122,255,0.0)",1,"rgba(0,122,255,0.0)"],c=["interpolate",["linear"],["line-progress"],0,"rgba(255,255,255,0.7)",a,"rgba(255,255,255,0.7)",l,"rgba(255,255,255,0.0)",1,"rgba(255,255,255,0.0)"];i.getLayer("route-line")&&i.setPaintProperty("route-line","line-gradient",u),i.getLayer("route-halo")&&i.setPaintProperty("route-halo","line-gradient",c),this.routeAnimationFrame=r<1?requestAnimationFrame(e):null};this.routeAnimationFrame=requestAnimationFrame(e)}stopRouteAnimation(){this.routeActive=!1,null!=this.routeAnimationFrame&&"undefined"!=typeof window&&cancelAnimationFrame(this.routeAnimationFrame),this.routeAnimationFrame=null,this.routeAnimationStart=null;const t=this.deps.getMap();t&&(t.getLayer("route-line")&&(t.setPaintProperty("route-line","line-gradient",void 0),t.setPaintProperty("route-line","line-color","#007aff")),t.getLayer("route-halo")&&(t.setPaintProperty("route-halo","line-gradient",void 0),t.setPaintProperty("route-halo","line-color","#ffffff")))}}class S{getVenue;getFloors;getFloorById;logFn;constructor(t){this.getVenue=t.getVenue,this.getFloors=t.getFloors,this.getFloorById=t.getFloorById,this.logFn=t.log}get venue(){return this.getVenue()}log(...t){this.logFn&&this.logFn(...t)}loadForFloor(t){if(!t||!this.venue)return[];try{const e=this.venue.amenities?.getByMap(t.id)||[];return Array.isArray(e)?e.map(e=>{const o=e;return o.floorId=t.id,o}):[]}catch{return[]}}getAll(){return this.getFloors().flatMap(t=>this.loadForFloor(t))}getByFloorId(t){const e=this.getFloorById(t);return e?this.loadForFloor(e):[]}getAllKiosks(){return this.getAll().filter(t=>A(t))}getKioskForFloor(t){const e=this.getFloorById(t);if(!e)return null;return this.loadForFloor(e).find(t=>A(t))??null}logKioskForFloor(t){const e=this.getFloorById(t);if(!e)return;const o=this.getKioskForFloor(t);o?this.log("amenity :: kiosk found",{floorId:e.id,id:o.id,name:o.name,keywords:o.keywords,waypoints:o.waypoints,raw:o}):this.log("amenity :: kiosk not found on floor",{floorId:e.id})}}c({enabled:!0,prefix:"MinuteMapsSDK"});class E{mode;proxyBaseUrl;direct;fetchImpl;tokenCache=null;constructor(t){const e="undefined"!=typeof window?window:globalThis,o=t.fetchImpl??e.fetch;if("function"!=typeof o)throw new Error("Fetch API is not available in this environment");this.fetchImpl=o.bind(e),this.mode=t.mode,this.proxyBaseUrl=("proxy"===t.mode?t.proxyBaseUrl:void 0)||"/api/jacs","direct"===t.mode?this.direct={host:this.normalizeHost(t.host),clientId:t.clientId,username:t.username,password:t.password}:this.direct=null}async getPolygonLayers(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/polygon-layer`,o=await this.getJson(e);return this.extractArray(o)}async getFloorMapTemplate3d(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/building/${encodeURIComponent(String(t.buildingId))}/floor/${encodeURIComponent(String(t.floorId))}/map-template/3d`,o=await this.getJson(e);return this.extractArray(o)}async getFloors(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/building/${encodeURIComponent(String(t.buildingId))}/floor`,o=await this.getJson(e);return this.extractArray(o)}async getVenue(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}`,o=await this.getJson(e),i=o?.venue||o?.data||o;if(!i||"object"!=typeof i)throw new Error("JACS venue response was not a JSON object");return i}async getFloorMapGeojson(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/building/${encodeURIComponent(String(t.buildingId))}/floor/${encodeURIComponent(String(t.floorId))}/map/geojson`,o=await this.getJson(e),i=o?.geojson||o?.data||o;if(!i||"FeatureCollection"!==i.type||!Array.isArray(i.features))throw new Error("JACS floor geojson did not look like a GeoJSON FeatureCollection");return i}async getBuildingFull(t){const e=new URLSearchParams;e.set("mapProfile",String(t.mapProfile??"public")),e.set("geojson",String(t.geojson??!0));const o=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/building/${encodeURIComponent(String(t.buildingId))}/full?${e.toString()}`,i=await this.getJson(o),n=i?.data||i?.result||i;if(!n||"object"!=typeof n)throw new Error("JACS building full response was not a JSON object");return n}async getDestinations(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/destination`,o=await this.getJson(e);return this.extractArray(o)}async getAmenities(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/amenity`,o=await this.getJson(e);return this.extractArray(o)}async getBuildings(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/building`,o=await this.getJson(e);return this.extractArray(o)}async getStylesheet3d(t){const e=`/customer/${encodeURIComponent(String(t.customerId))}/venue/${encodeURIComponent(String(t.venueId))}/building/${encodeURIComponent(String(t.buildingId))}/stylesheet/3d`,o=await this.getJson(e),i=o?.style||o?.data||o;if(!i||"object"!=typeof i)throw new Error("JACS stylesheet response was not a JSON object");return i}invalidateToken(){this.tokenCache=null}async getJson(t){if("proxy"===this.mode){const e=this.proxyBaseUrl.replace(/\/+$/,""),o=t.startsWith("/")?t:`/${t}`,i=await this.fetchImpl(`${e}${o}`,{method:"GET",headers:{Accept:"application/json"}});if(!i.ok){const t=await this.safeReadText(i);throw new Error(`JACS proxy GET failed (${i.status} ${i.statusText}) :: ${t}`)}return await i.json()}const e=this.direct;if(!e)throw new Error("JacsProvider is not configured for direct mode");const o=await this.getJwtToken(),i=this.joinUrl(e.host,t),n=await this.fetchImpl(i,{method:"GET",headers:{Authorization:`Bearer ${o}`,Accept:"application/json"}});if(!n.ok){const t=await this.safeReadText(n);throw new Error(`JACS GET failed (${n.status} ${n.statusText}) :: ${t}`)}return await n.json()}extractArray(t){return(Array.isArray(t)?t:null)||(Array.isArray(t?.data)?t.data:null)||(Array.isArray(t?.items)?t.items:null)||(Array.isArray(t?.results)?t.results:null)||[]}async getJwtToken(){const t=this.direct;if(!t)throw new Error("getJwtToken should not be called in proxy mode");const e=Date.now(),o=this.tokenCache;if(o?.token&&e<o.expiresAtMs-3e4)return o.token;const i=this.joinUrl(t.host,"/auth/token"),n=new URLSearchParams;n.set("grant_type","password"),n.set("client_id",t.clientId),n.set("username",t.username),n.set("password",t.password);const r=await this.fetchImpl(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:n.toString()});if(!r.ok){const t=await this.safeReadText(r);throw new Error(`JACS auth failed (${r.status} ${r.statusText}) :: ${t}`)}const s=await r.json(),a=s?.access_token||s?.token||s?.jwt||s?.accessToken;if(!a)throw new Error("JACS auth response did not contain a token");const l=s?.expires_in??s?.expiresIn??s?.expires??s?.ttl,u="number"==typeof l?l:Number(l),c=Number.isFinite(u)&&u>0?u:600;return this.tokenCache={token:a,expiresAtMs:Date.now()+1e3*c},a}normalizeHost(t){return String(t||"").replace(/\/+$/,"")}joinUrl(t,e){const o=this.normalizeHost(t),i=String(e||"");return i?`${o}${i.startsWith("/")?"":"/"}${i}`:o}async safeReadText(t){try{return await t.text()}catch{return""}}}const M=c({enabled:!0,prefix:"MinuteMapsSDK jacs"});class B{config;jacs;floors=[];buildingId=null;destinationsByMapId=new Map;amenitiesByMapId=new Map;venueLike=null;async init(t){this.config=t;const e=t.jacs;if(!e?.mode)throw new Error("config.jacs.mode is required");if("proxy"!==e.mode){if(!e.host)throw new Error("config.jacs.host is required (direct mode)");if(!e.auth?.clientId)throw new Error("config.jacs.auth.clientId is required (direct mode)");if(!e.auth?.username)throw new Error("config.jacs.auth.username is required (direct mode)");if(!e.auth?.password)throw new Error("config.jacs.auth.password is required (direct mode)");this.jacs=new E({mode:"direct",host:e.host,clientId:e.auth.clientId,username:e.auth.username,password:e.auth.password})}else this.jacs=new E({mode:"proxy",proxyBaseUrl:e.proxyBaseUrl||"/api/jacs"})}async loadVenue(){const t=this.config.jmap.customerId,e=this.config.jmap.venueId;if(null==t)throw new Error("config.jmap.customerId is required");if(null==e)throw new Error("config.jmap.venueId is required");const o=await this.jacs.getBuildings({customerId:t,venueId:e}),i=o[0]?.id??o[0]?.buildingId;if(0===o.length||!i)throw new Error("No buildings found for this customer and venue");const[n,r]=await Promise.all([this.jacs.getVenue({customerId:t,venueId:e}),this.jacs.getBuildingFull({customerId:t,venueId:e,buildingId:i,mapProfile:"public",geojson:!0})]);this.buildingId=i;const s=(r?.floors?.items??r?.floors??[]).map(t=>{const e=t.map??{};return{id:t.id,name:t.name??t.shortName??String(t.id),sequence:t.level??t.preference,isDefault:t.id===r?.defaultFloorId,geojson:e.geojson??null,mapTemplate3d:[],_waypoints:e.waypoints?.items??[]}});this.floors=s;let a=[],l=[];try{const o=await this.jacs.getJson(`/customer/${t}/venue/${e}/full?mapProfile=public`);a=o?.destinations?.items??[],l=o?.amenities?.items??[]}catch{try{a=await this.jacs.getDestinations({customerId:t,venueId:e})}catch{}try{l=await this.jacs.getAmenities({customerId:t,venueId:e})}catch{}}this.amenitiesByMapId.clear();for(const t of l)for(const e of t?.waypoints??[]){const o=e?.mapId;if(null==o)continue;const i=this.amenitiesByMapId.get(o)??[];i.push(t),this.amenitiesByMapId.set(o,i)}this.destinationsByMapId.clear();for(const t of a)for(const e of t?.waypoints??[]){const o=e?.mapId;if(null==o)continue;const i=this.destinationsByMapId.get(o)??[];i.push(t),this.destinationsByMapId.set(o,i)}return this.venueLike={...n,floors:s,polygonLayers:[],destinations:{items:[...a],getByMap:({id:t})=>this.destinationsByMapId.get(t)??[]},amenities:{items:[...l],getByMap:({id:t})=>this.amenitiesByMapId.get(t)??[]},buildings:{items:[...o],getAllFloors:()=>this.floors},styleSheet:null},this.venueLike}async ensureFloorGeojson(t){if(t.geojson)return;const e=this.config.jmap.customerId,o=this.config.jmap.venueId;try{const i=await this.jacs.getFloorMapGeojson({customerId:e,venueId:o,buildingId:this.buildingId,floorId:t.id});t.geojson=function(t){return(t?.type?t:t?.data)??null}(i)}catch(e){M.warn("floor geojson fetch failed",{floorId:t.id,e:e})}}async preloadRemainingFloors(){const t=this.floors.filter(t=>!t.geojson);0!==t.length&&(await Promise.all(t.map(t=>this.ensureFloorGeojson(t))),M.debug("preloaded geojson for remaining floors",{count:t.length}))}async getFloors(){return this.floors}async getAmenities(t){return this.amenitiesByMapId.get(t)??[]}async getDestinations(t){return this.destinationsByMapId.get(t)??[]}}class k{handlers=new Map;on(t,e){this.handlers.has(t)||this.handlers.set(t,new Set),this.handlers.get(t).add(e)}off(t,e){e?this.handlers.get(t)?.delete(e):this.handlers.delete(t)}emit(t,e){this.handlers.get(t)?.forEach(t=>{try{t(e)}catch{}})}}var z={version:8,name:"Hospital Indoor Mapping - Hybrid Style Healthcare Compliant",metadata:{description:"Accessibility-focused hospital navigation with proper healthcare standards",author:"Hospital Mapping Team",version:"7.1.0"},sprite:"http://localhost:4000/sprites/sprite",glyphs:"https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",sources:{"osm-tiles":{type:"raster",tiles:["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],tileSize:256,attribution:"© OpenStreetMap contributors"},"indoor-data":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"poi-data":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"accessibility-data":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"unit-walls":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"route-data":{type:"geojson",data:{type:"FeatureCollection",features:[]},lineMetrics:!0},"route-endpoints":{type:"geojson",data:{type:"FeatureCollection",features:[]}}},layers:[{id:"background",type:"background",paint:{"background-color":"#F5F5F5"}},{id:"osm",type:"raster",source:"osm-tiles",minzoom:0,paint:{"raster-opacity":["interpolate",["linear"],["zoom"],14,.8,16,.6,18,.4]}},{id:"pattern-water",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Water"],paint:{"fill-color":"#5DADE2","fill-opacity":.6}},{id:"pattern-grass",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Grass"],paint:{"fill-color":"#7CB342","fill-opacity":.5}},{id:"pattern-trees",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Trees"],paint:{"fill-color":"#4CAF50","fill-opacity":.4}},{id:"pattern-pavement",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Pavement"],paint:{"fill-color":"#E0E0E0","fill-opacity":.6}},{id:"pattern-outdoor-terrace",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-OutdoorTerrace"],paint:{"fill-color":"#8D6E63","fill-opacity":.3}},{id:"parking-lots",type:"fill",source:"indoor-data",filter:["==",["get","featureType"],"Parking-Lots"],paint:{"fill-color":"#BDBDBD","fill-opacity":.6}},{id:"parking-lots-outline",type:"line",source:"indoor-data",filter:["==",["get","featureType"],"Parking-Lots"],paint:{"line-color":"#757575","line-width":1,"line-dasharray":[3,2]}},{id:"boundary-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],paint:{"fill-color":"#FAF3E2","fill-opacity":1}},{id:"building-roof-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],paint:{"fill-color":"#6A8799","fill-opacity":1}},{id:"corridors-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["any",["==",["get","featureType"],"Corridors"],["==",["get","featureType"],"Corridor"]],paint:{"fill-color":"#F0E6D1"}},{id:"accessible-routes",type:"line",source:"accessibility-data",minzoom:16.5,filter:["==",["get","accessible"],!0],paint:{"line-color":"#2E7D32","line-width":["interpolate",["linear"],["zoom"],15,2,18,3,20,4],"line-dasharray":[.5,1],"line-opacity":.7}},{id:"units-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Units"],paint:{"fill-color":["case",["has","category"],["match",["get","category"],"healthcare","#7C3AED","emergency","#DC2626","diagnostic","#0EA5E9","surgical","#7C3AED","retail","#FF6B6B","fnb","#FFA500","admin","#A29BFE","amenities","#48C9B0","staff","#74B9FF","security","#1A7A96","waiting","#E1BEE7","#8ecae6"],"#8ecae6"],"fill-opacity":["interpolate",["linear"],["zoom"],15,.85,17,.92,19,.95]}},{id:"units-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Units"],layout:{visibility:"none","line-join":"round","line-cap":"round"},paint:{"line-color":"#263238","line-opacity":.9,"line-width":["interpolate",["linear"],["zoom"],16,.6,18,1,20,1.6]}},{id:"backofhouse-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],paint:{"fill-color":"#D6D6CC","fill-opacity":.7}},{id:"backofhouse-pattern",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],paint:{"line-color":"#90A4AE","line-width":.5,"line-opacity":.4}},{id:"backofhouse-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#7B8D93","line-width":["interpolate",["linear"],["zoom"],16,.6,18,1,20,1.4],"line-opacity":.9}},{id:"restrooms-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Restrooms"],paint:{"fill-color":"#5B8468","fill-opacity":1}},{id:"restrooms-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Restrooms"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#3F5D4A","line-width":["interpolate",["linear"],["zoom"],16,.6,18,1,20,1.4],"line-opacity":.9}},{id:"obstacles-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Obstacles"],paint:{"fill-color":"#E8E9ED","fill-opacity":.85}},{id:"obstacles-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Obstacles"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#B0B1B5","line-width":["interpolate",["linear"],["zoom"],16,.5,18,.9,20,1.2],"line-opacity":.9}},{id:"escalators-stairs-elevators",type:"fill",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Escalators","Stairs","Elevators"]]],paint:{"fill-color":"#6A8799","fill-opacity":1}},{id:"escalators-stairs-elevators-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Escalators","Stairs","Elevators"]]],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#455A64","line-width":["interpolate",["linear"],["zoom"],16,.6,18,1,20,1.4],"line-opacity":.9}},{id:"exits-doors",type:"fill",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Exits","Doors","Exit","Door"]]],paint:{"fill-color":"#4CAF50","fill-opacity":.6}},{id:"kiosks-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Kiosks"],paint:{"fill-color":"#9C27B0","fill-opacity":.7}},{id:"pattern-lounge",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Lounge"],paint:{"fill-color":"#CE93D8","fill-opacity":.5}},{id:"pattern-indoor-foodcourt",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-IndoorFoodcourt"],paint:{"fill-color":"#FFCC80","fill-opacity":.6}},{id:"corridors-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["any",["==",["get","featureType"],"Corridors"],["==",["get","featureType"],"Corridor"]],paint:{"line-color":"#BCAAA4","line-width":["interpolate",["linear"],["zoom"],15,.5,18,1,20,1.5]}},{id:"boundary-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],paint:{"line-color":"#263238","line-width":["interpolate",["linear"],["zoom"],12,2,15,2.5,18,3,20,3.5],"line-opacity":["interpolate",["linear"],["zoom"],12,.7,17,.85,18,1]}},{id:"building-roof-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#263238","line-width":["interpolate",["linear"],["zoom"],15,1.2,18,1.8,20,2.4],"line-opacity":.95}},{id:"interior-parking-lots",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Interior-ParkingLots"],paint:{"fill-color":"#757575","fill-opacity":.8}},{id:"interior-parking-lots-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Interior-ParkingLots"],paint:{"line-color":"#616161","line-width":1.5}},{id:"building-extrusion",type:"fill-extrusion",source:"indoor-data",filter:["==",["get","featureType"],"Boundary"],maxzoom:16.5,paint:{"fill-extrusion-color":"#6A8799","fill-extrusion-height":15,"fill-extrusion-base":0,"fill-extrusion-opacity":1}},{id:"units-wall-extrusion",type:"fill-extrusion",source:"unit-walls",minzoom:16.5,filter:["all",["==",["get","featureType"],"UnitWalls"],["!",["has","custom_height"]]],paint:{"fill-extrusion-color":["case",["has","category"],["match",["get","category"],"healthcare","#5B2DB8","emergency","#B91C1C","diagnostic","#0C7FAB","surgical","#5B2DB8","retail","#CC5555","fnb","#CC8400","admin","#7B73CC","amenities","#3A9B88","staff","#5C96CC","security","#135C75","waiting","#B894C2","#eeeeee"],"#eeeeee"],"fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-vertical-gradient":!1,"fill-extrusion-opacity":.9}},{id:"units-wall-custom-extrusion",type:"fill-extrusion",source:"unit-walls",minzoom:16.5,filter:["has","custom_height"],paint:{"fill-extrusion-color":["case",["has","category"],["match",["get","category"],"healthcare","#5B2DB8","emergency","#B91C1C","diagnostic","#0C7FAB","surgical","#5B2DB8","retail","#CC5555","fnb","#CC8400","admin","#7B73CC","amenities","#3A9B88","staff","#5C96CC","security","#135C75","waiting","#B894C2","#FDFAF2"],"#FDFAF2"],"fill-extrusion-height":["to-number",["get","custom_height"]],"fill-extrusion-base":0,"fill-extrusion-vertical-gradient":!1,"fill-extrusion-opacity":.95}},{id:"corridors-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["any",["==",["get","featureType"],"Corridors"],["==",["get","featureType"],"Corridor"]],layout:{visibility:"none"},paint:{"fill-extrusion-color":"#FFF8E1","fill-extrusion-height":["step",["zoom"],0,18,3.2],"fill-extrusion-base":0,"fill-extrusion-opacity":["step",["zoom"],0,18,.85]}},{id:"backofhouse-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],paint:{"fill-extrusion-color":"#D6D6CC","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-opacity":1}},{id:"restrooms-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Restrooms"],paint:{"fill-extrusion-color":"#5B8468","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-opacity":.9}},{id:"obstacles-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Obstacles"],paint:{"fill-extrusion-color":"#E8E9ED","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,.8,17.5,1.5,18.2,2],"fill-extrusion-base":0,"fill-extrusion-opacity":1}},{id:"escalators-stairs-elevators-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Escalators","Stairs","Elevators"]]],paint:{"fill-extrusion-color":"#6A8799","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-vertical-gradient":!0,"fill-extrusion-opacity":.9}},{id:"interior-parking-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Interior-ParkingLots"],paint:{"fill-extrusion-color":"#757575","fill-extrusion-height":["interpolate",["linear"],["zoom"],15,0,16,2,17,3,18,4],"fill-extrusion-base":0,"fill-extrusion-opacity":.85}},{id:"route-line",type:"line",source:"route-data",minzoom:16.5,layout:{"line-cap":"round","line-join":"round"},paint:{"line-color":"#007aff","line-width":["interpolate",["linear"],["zoom"],16.5,3,18,5,20,7],"line-opacity":.9}},{id:"route-halo",type:"line",source:"route-data",minzoom:16.5,paint:{"line-color":"white","line-width":["interpolate",["linear"],["zoom"],16.5,5,18,7,20,9],"line-opacity":.7}},{id:"route-endpoint-source",type:"circle",source:"route-endpoints",minzoom:16.5,filter:["==",["get","role"],"source"],paint:{"circle-radius":6,"circle-color":"#ffffff","circle-stroke-width":3,"circle-stroke-color":"#007aff","circle-opacity":1}},{id:"route-endpoint-destination",type:"circle",source:"route-endpoints",minzoom:16.5,filter:["==",["get","role"],"destination"],paint:{"circle-radius":7,"circle-color":"#007aff","circle-stroke-width":3,"circle-stroke-color":"#ffffff","circle-opacity":1}},{id:"poi-accessibility-icons",type:"symbol",source:"poi-data",filter:["==",["get","accessible"],!0],minzoom:16.5,layout:{"icon-image":"wheelchair-accessible","icon-size":["interpolate",["linear"],["zoom"],15,.4,17,.6,19,.8],"icon-allow-overlap":!1,"icon-padding":4}},{id:"poi-destination-circles",type:"circle",source:"poi-data",filter:["==",["get","poiType"],"destination"],minzoom:16.5,paint:{"circle-radius":["interpolate",["linear"],["zoom"],15,3,17,4,19,5,20,6],"circle-color":"#162e51","circle-stroke-width":2,"circle-stroke-color":"#FFFFFF","circle-opacity":.9}},{id:"poi-destination-labels",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"destination"],["==",["get","showLabel"],!0]],minzoom:18.5,layout:{"text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],18.5,12,20,14],"text-offset":[0,.8],"text-anchor":"top","text-font":["Noto Sans Bold"],"text-max-width":12,"text-allow-overlap":!1,"text-rotation-alignment":"viewport"},paint:{"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1}},{id:"poi-entrance-exit-icons",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"amenity"],["any",["!=",["index-of","entrance",["get","keywords"]],-1],["!=",["index-of","exit",["get","keywords"]],-1],["!=",["index-of","door",["get","keywords"]],-1]]],minzoom:15,layout:{"icon-image":["get","iconId"],"icon-size":["interpolate",["linear"],["zoom"],16.5,.5,18,.6,20,.8],"icon-allow-overlap":!0,"icon-padding":2,"icon-optional":!1,"icon-rotation-alignment":"viewport","icon-pitch-alignment":"viewport","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],16.5,0,18.5,0,19,12,20,13],"text-offset":[0,1.3],"text-anchor":"top","text-optional":!0,"text-padding":4,"text-font":["Noto Sans Bold"],"text-rotation-alignment":"viewport"},paint:{"icon-halo-color":"#FFFFFF","icon-halo-width":1.5,"icon-halo-blur":.5,"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1,"icon-translate":[0,-20],"icon-translate-anchor":"viewport"}},{id:"poi-parking-icons",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"amenity"],["any",["!=",["index-of","parking",["get","keywords"]],-1],["!=",["index-of","park",["get","keywords"]],-1]]],minzoom:14,layout:{"icon-image":["get","iconId"],"icon-size":["interpolate",["linear"],["zoom"],16.5,.5,18,.6,20,.8],"icon-allow-overlap":!0,"icon-padding":2,"icon-optional":!1,"icon-rotation-alignment":"viewport","icon-pitch-alignment":"viewport","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],16.5,0,18.5,0,19,12,20,13],"text-offset":[0,1.3],"text-anchor":"top","text-optional":!0,"text-padding":4,"text-font":["Noto Sans Bold"],"text-rotation-alignment":"viewport"},paint:{"icon-halo-color":"#FFFFFF","icon-halo-width":1.5,"icon-halo-blur":.5,"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1,"icon-translate":[0,-20],"icon-translate-anchor":"viewport"}},{id:"poi-other-amenity-icons",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"amenity"],["==",["index-of","entrance",["get","keywords"]],-1],["==",["index-of","exit",["get","keywords"]],-1],["==",["index-of","door",["get","keywords"]],-1],["==",["index-of","parking",["get","keywords"]],-1],["==",["index-of","park",["get","keywords"]],-1]],minzoom:17.5,layout:{"icon-image":["get","iconId"],"icon-size":["interpolate",["linear"],["zoom"],17.5,.5,18,.6,20,.8],"icon-allow-overlap":!0,"icon-padding":2,"icon-optional":!1,"icon-rotation-alignment":"viewport","icon-pitch-alignment":"viewport","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],17.5,0,18.5,0,19,12,20,13],"text-offset":[0,1.3],"text-anchor":"top","text-optional":!0,"text-padding":4,"text-font":["Noto Sans Bold"],"text-rotation-alignment":"viewport"},paint:{"icon-halo-color":"#FFFFFF","icon-halo-width":1.5,"icon-halo-blur":.5,"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1,"icon-translate":[0,-20],"icon-translate-anchor":"viewport"}},{id:"poi-you-are-here",type:"symbol",source:"poi-data",filter:["==",["get","isYouAreHere"],!0],minzoom:16.5,layout:{"icon-image":["coalesce",["get","iconId"],"you-are-here"],"icon-size":["interpolate",["linear"],["zoom"],16.5,.8,18,1,20,1.2],"icon-allow-overlap":!0,"icon-ignore-placement":!0,"icon-anchor":"bottom","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],17.5,11,19.5,13],"text-offset":[0,1.2],"text-anchor":"top","text-font":["Noto Sans Bold"],"text-optional":!0},paint:{"text-color":"#ffffff","text-halo-color":"#000000","text-halo-width":1.5,"text-halo-blur":.8}}]};function j(t,e,o={}){t.sources||={},t.sources[e]||(t.sources[e]={type:"geojson",data:{type:"FeatureCollection",features:[]},...o})}function P(t){let e=structuredClone(t.style);if(e.sprite=t.customSprite||e.sprite||t.defaultSpriteUrl,j(e,n),j(e,s),j(e,r),j(e,a,{lineMetrics:!0}),j(e,"route-endpoints"),t.floorLayers)for(const o of Object.keys(t.floorLayers))j(e,`amenity_${o}`),j(e,`destination_${o}`),j(e,`pathTypes_${o}`);return e}const T="https://demotiles.maplibre.org/styles/osm-bright-gl-style/sprite";class D{config;map=null;data=new B;wayfindingProvider={wayfindBetweenWaypoints:async()=>{throw new Error("Wayfinding is not yet implemented in the SDK")}};events=new k;floorsApi;venue=null;spriteKeys=null;debug;logger;defaultCamera=null;viewModes;amenityManager;wayfinding;constructor(t){this.config=t,this.debug=Boolean(t.debug??t.options?.debug),this.logger=c({enabled:this.debug,prefix:"MinuteMapsSDK"}),this.viewModes=new w(()=>this.map),this.floorsApi=new p({getMap:()=>this.map,getConfig:()=>this.config,updatePoiSource:async t=>{const e=this.map;if(!e)return;const o=this.getAllPOIs(t),n=F.toFeatureCollection(o);i.setData(e,r,n)},log:(...t)=>this.logger.debug(...t)}),this.amenityManager=new S({getVenue:()=>this.venue,getFloors:()=>this.floorsApi.getFloors(),getFloorById:t=>this.floorsApi.getFloors().find(e=>e.id===t)??null,log:(...t)=>this.logger.debug(...t)}),this.wayfinding=new C({getMap:()=>this.map,getVenue:()=>this.venue,getYouAreHerePOI:t=>this.getYouAreHerePOI(t),getYouAreHereCoordinates:t=>this.getYouAreHereCoordinates(t),getBoundsPadding:()=>this.getBoundsPadding(),computeRoute:async(t,e)=>{const o=this.config.jmap.customerId,i=this.config.jmap.venueId;if(null==o)throw new Error("config.jmap.customerId is required");if(null==i)throw new Error("config.jmap.venueId is required");return this.wayfindingProvider.wayfindBetweenWaypoints({customerId:o,venueId:i,from:t,to:e})},log:(...t)=>this.logger.debug(...t),warn:(...t)=>this.logger.warn(...t),debug:this.debug})}async init(){const{venueId:e,customerId:o}=this.config?.jmap;if(null==e||null==o)throw new Error("config.jmap.customerId and config.jmap.venueId are required");if(!this.config.container)throw new Error("config.container is required (HTMLElement or element id)");this.logger.debug("init :: starting (JACS)",{venueId:e,customerId:o});try{await this.data.init(this.config),this.logger.debug("providers :: JACS ready"),this.venue=await this.data.loadVenue(),this.logger.debug("JACS :: venue loaded",this.venue.id),this.floorsApi.setFloors(this.venue.floors),this.logger.debug("JACS :: floors loaded",{count:this.venue.floors.length});const e=P({style:z,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:T});this.ensureFloorLayersFromStyle(e),this.map=function(e,o){const i="string"==typeof e?document.getElementById(e):e;if(!i)throw new Error("Map container not found");return new t.Map({container:i,style:o,center:[0,0],zoom:16,pitch:45,bearing:0})}(this.config.container,e),await new Promise(t=>this.map.once("load",()=>t())),this.map.on("error",t=>{const e=t?.error?.message||t?.message||t;this.logger.error("map :: error",{msg:e,sourceId:t?.sourceId,tile:t?.tile})}),this.map.on("styledata",()=>{try{this.viewModes.onStyleData()}catch{}}),this.map.on("move",()=>{if(!this.map)return;const t=b(this.map);t&&this.events.emit("cameraChange",{camera:t})}),this.ensureCoreSources(),this.spriteKeys=await h.getSpriteKeys(this.map);const o=this.floorsApi.getInitialFloor();Boolean(o?.geojson?.features?.length)||this.applyInitialViewFromVenue(),o&&await this.setCurrentFloor(o),this.defaultCamera=b(this.map),this.events.emit("ready",{venue:this.venue}),this.events.emit("floorsLoaded",{})}catch(t){throw this.logger.error("init :: failed (JACS)",t),this.events.emit("error",{error:t}),t}}on(t,e){this.events.on(t,e)}off(t,e){this.events.off(t,e)}addControl(t,e){this.map?.addControl(t,e)}setView(t){!function(t,e){if(!t)return;const{center:o,zoom:i,pitch:n,bearing:r,animate:s,duration:a}=e;if(s){const e=t.getCenter(),s=o||[e.lng,e.lat],l=i??t.getZoom(),u=n??t.getPitch(),c=r??t.getBearing(),d="number"==typeof a?a:900;return void t.flyTo({center:s,zoom:l,pitch:u,bearing:c,duration:d,essential:!0})}o&&t.setCenter(o),void 0!==i&&t.setZoom(i),void 0!==n&&t.setPitch(n),void 0!==r&&t.setBearing(r)}(this.map,t)}get amenities(){return this.amenityManager}resetView(t){!function(t,e,o){if(!t||!e)return;const{center:i,zoom:n,pitch:r,bearing:s}=e,a=Boolean(o?.animate),l="number"==typeof o?.duration?o.duration:800;a?t.easeTo({center:i,zoom:n,pitch:r,bearing:s,duration:l}):t.jumpTo({center:i,zoom:n,pitch:r,bearing:s})}(this.map,this.defaultCamera,t)}set3dEnabled(t){this.viewModes.set3dEnabled(t)}toggle3d(){this.viewModes.toggle3d()}getIs3dEnabled(){return this.viewModes.getIs3dEnabled()}setUnits2dEnabled(t){this.viewModes.setUnits2dEnabled(t)}toggleUnits2d(){this.viewModes.toggleUnits2d()}getIsUnits2dEnabled(){return this.viewModes.getIsUnits2dEnabled()}setFlatMode(t){this.viewModes.setFlatMode(t)}toggleFlatMode(){this.viewModes.toggleFlatMode()}getIsFlatMode(){return this.viewModes.getIsFlatMode()}getFloors(){return this.floorsApi.getFloors()}getCurrentFloor(){return this.floorsApi.getCurrentFloor()}getDefaultFloor(){return this.floorsApi.getDefaultFloor()}getDestinations(t){const e=t||this.getCurrentFloor();return function(t,e){if(!t||!e)return[];try{const o=t.destinations?.getByMap?.({id:e.id})||[];return Array.isArray(o)?o:[]}catch{return[]}}(this.venue,e)}getPolygonLayers(){return this.venue?.polygonLayers??[]}getFloorMapTemplate3d(t){return this.venue?.mapTemplates3d?.[String(t)]??[]}getAllPOIs(t){const e=t||this.getCurrentFloor();if(!e)return[];return function(t,e,o,i){return F.buildPOIs(t,e,o,i)}(e,this.amenityManager.getByFloorId(e.id),this.getDestinations(e),this.spriteKeys)}getYouAreHerePOI(t){return x(this.getAllPOIs(t))}getYouAreHereCoordinates(t){return function(t){const e=x(t);return e?.coordinates??null}(this.getAllPOIs(t))}searchPOIs(t,e){return function(t,e){const o=e.trim().toLowerCase();return o?t.filter(t=>{const e=t.name?.toLowerCase().includes(o),i=(t.keywords||[]).some(t=>t.toLowerCase().includes(o));return e||i}):[]}(this.getAllPOIs(e),t)}async wayfindBetweenWaypoints(t,e,o){return this.wayfinding.wayfindBetweenWaypoints(t,e,o)}async navigateFromKioskToDestination(t){return this.wayfinding.navigateFromKioskToDestination(t)}clearRoute(){this.wayfinding.clearRoute()}getCameraPosition(){return b(this.map)}getMap(){return this.map}destroy(){this.map?.remove(),this.map=null,this.floorsApi.setFloors([]),this.defaultCamera=null,this.viewModes=new w(()=>this.map)}async setCurrentFloor(t){await this.data.ensureFloorGeojson(t),await this.floorsApi.setCurrentFloor(t),this.setFloorLayerVisibility(t.id),this.events.emit("floorChanged",{floor:t})}isReady(){return!!this.map}setFloorLayerVisibility(t){const e=this.map;if(!e)return;const o=this.venue?.styleSheet?.floorLayers;if(o)for(const[i,n]of Object.entries(o)){const o=String(i)===String(t);for(const t of n)e.getLayer(t.id)&&e.setLayoutProperty(t.id,"visibility",o?"visible":"none")}}getBoundsPadding(){return this.config.options?.boundsPadding??50}getVenueBounds(){const t=this.venue?.coordinates;if(!t)return null;const{bottomLng:e,bottomLat:o,topLng:i,topLat:n}=t;if(null==e||null==o||null==i||null==n)return null;const r=Math.min(e,i),s=Math.max(e,i);return[[r,Math.min(o,n)],[s,Math.max(o,n)]]}applyInitialViewFromVenue(){const t=this.map;if(!t)return;const e=this.getVenueBounds();if(e)try{t.resize(),t.fitBounds(e,{padding:this.getBoundsPadding(),animate:!1,duration:0,maxZoom:21})}catch(t){this.logger.warn("applyInitialViewFromVenue :: fitBounds failed",t)}}async loadAndPatchVenueStyle(){const t=this.venue?.styleSheet?.styleUrl,e=this.venue?.styleSheet?.floorLayers,o=z;if("sdkTemplate"===this.config.options?.styleMode)return this.logger.debug("style :: styleMode=sdkTemplate, ignoring venue styleUrl"),P({style:o,floorLayers:e,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:T});if(!t)return this.logger.warn("style :: venue.styleSheet.styleUrl missing, using baseStyle"),P({style:o,floorLayers:e,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:T});try{const o=await fetch(t);if(!o.ok)throw new Error(`HTTP ${o.status} ${o.statusText}`);return P({style:await o.json(),floorLayers:e,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:T})}catch(t){return this.logger.warn("style :: failed to fetch venue styleUrl, using baseStyle",t),P({style:o,floorLayers:e,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:T})}}ensureFloorLayersFromStyle(t){const e=this.venue?.styleSheet?.floorLayers;if(e&&Object.keys(e).length)return;const o={};for(const e of t.layers||[]){const t=e.id||"",i=/_(\d+)$/.exec(t);if(!i)continue;const n=i[1];o[n]||=[],o[n].push({id:t})}this.venue||={},this.venue.styleSheet||={},this.venue.styleSheet.floorLayers=o}ensureCoreSources(){const t=this.map;if(!t)return;const e={type:"FeatureCollection",features:[]};i.ensureGeoJson(t,n),i.ensureGeoJson(t,s),i.ensureGeoJson(t,r),t.getSource(a)||t.addSource(a,{type:"geojson",data:e,lineMetrics:!0}),t.getSource("route-endpoints")||t.addSource("route-endpoints",{type:"geojson",data:e})}}exports.MinuteMaps=D,exports.createMinuteMapsSDK=function(t){return new D(t)};
1
+ "use strict";var e=require("maplibre-gl");function t(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(o){if("default"!==o){var i=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,i.get?i:{enumerable:!0,get:function(){return e[o]}})}}),t.default=e,Object.freeze(t)}var o=t(require("@turf/turf"));const i={ensureGeoJson(e,t){e.getSource(t)||e.addSource(t,{type:"geojson",data:{type:"FeatureCollection",features:[]}})},setData(e,t,o){const i=e.getSource(t);i?.setData?.(o)}},n="indoor-data",r="poi-data",s="unit-walls",a="route-data",l=["boundary-fill","boundary-outline","units-fill","units-wall-extrusion","units-wall-custom-extrusion","corridors-fill","corridors-outline","building-extrusion"],u=()=>{};function c(e){const t=Boolean(e?.enabled),o=function(e){const t=String(e||"").trim();return t?`[${t}]`:""}(e?.prefix||"MinuteMapsSDK");return t?{debug:(...e)=>console.debug(o,...e),log:(...e)=>console.log(o,...e),warn:(...e)=>console.warn(o,...e),error:(...e)=>console.error(o,...e)}:{debug:u,log:u,warn:u,error:u}}c({enabled:!0,prefix:"MinuteMapsSDK"});const d={applyFloor(e,t,o=1){d.updateWalls(e,t,o),d.updateIndoor(e,t,o)},updateIndoor(e,t,r=1){const s=function(e,t){if(!e)return{type:"FeatureCollection",features:[]};if(!Number.isFinite(t)||t<=0)return e;const i=(e.features||[]).map(e=>{const i=e?.properties?.featureType;if(!i||!p.has(i))return e;const n=e?.geometry?.type;if("Polygon"!==n&&"MultiPolygon"!==n)return e;try{const i=o.buffer(e,-t,{units:"feet"});return i?.geometry?{...e,geometry:i.geometry}:e}catch{return e}});return{...e,features:i}}(t.geojson,r);i.setData(e,n,s);try{const e=t?.geojson?.features||[],o={};for(const t of e){const e=t?.properties?.featureType,i=null==e?"(missing)":String(e);o[i]=(o[i]||0)+1}Object.entries(o).sort((e,t)=>t[1]-e[1]).slice(0,15)}catch{}},updateWalls(e,t,n=1){const r=function(e,t=1){const i=(e.features||[]).filter(e=>"Units"===e.properties?.featureType).map(e=>{try{const i=o.buffer(e,-t,{units:"feet"});if(!i)return null;const n={...e.properties,featureType:"UnitWalls"};if(null==n.custom_height){const e=n.customProperties?.custom_height??n.custom_height??n.height??n.wall_height,t="number"==typeof e?e:Number(e);Number.isFinite(t)&&(n.custom_height=t)}return{type:"Feature",geometry:{type:"Polygon",coordinates:[e.geometry.coordinates[0],i.geometry.coordinates[0]]},properties:n}}catch{return null}}).filter(Boolean);return{type:"FeatureCollection",features:i}}(t.geojson,n);i.setData(e,s,r)},boundsFromGeoJson(e){try{const[t,i,n,r]=o.bbox(e),s=Math.min(t,n),a=Math.max(t,n),l=Math.min(i,r);return[[s,l],[a,Math.max(i,r)]]}catch{return null}},selectDefaultFloor:e=>Array.isArray(e)&&0!==e.length&&(e.find(e=>e.isDefault)||e[0])||null,selectInitialFloor(e,t){if(!Array.isArray(e)||0===e.length)return null;if(null!=t){const o=e.find(e=>e.id===t);if(o)return o}return d.selectDefaultFloor(e)},async activateFloor(e,t,o){if(!e)throw new Error("activateFloor requires an initialized map");if(t?.geojson&&d.applyFloor(e,t,o.wallFeet),await o.updatePOIs(t),!t?.geojson)return void(e.getZoom()<o.minIndoorZoom&&e.setZoom(o.minIndoorZoom));const i=d.boundsFromGeoJson(t.geojson);if(!i)return;const n=!o.didFit;let r=n;if(!r){const[[t,o],[n,s]]=i,a=e.getBounds();r=a.getWest()>n||a.getEast()<t||a.getSouth()>s||a.getNorth()<o}r?(e.fitBounds(i,{padding:o.boundsPadding,animate:!n,duration:700,bearing:e.getBearing(),pitch:e.getPitch()}),e.once("moveend",()=>{e.getZoom()<o.minIndoorZoom&&e.setZoom(o.minIndoorZoom)}),o.setDidFit(!0),o.log?.("camera :: fitToFloor",{floorId:t.id,animated:!n})):(e.getZoom()<o.minIndoorZoom&&e.setZoom(o.minIndoorZoom),o.log?.("camera :: fit skipped (floor overlaps viewport)",{floorId:t.id}))}},p=new Set(["Restrooms","Back-of-house","Obstacles","Escalators","Stairs","Elevators"]);class f{floors=[];currentFloor=null;didFit=!1;getMap;getConfig;updatePoiSource;logFn;constructor(e){this.getMap=e.getMap,this.getConfig=e.getConfig,this.updatePoiSource=e.updatePoiSource,this.logFn=e.log}log(...e){this.logFn&&this.logFn(...e)}setFloors(e){this.floors=e}getFloors(){return[...this.floors]}getCurrentFloor(){return this.currentFloor}setDidFit(e){this.didFit=e}getDefaultFloor(){return d.selectDefaultFloor(this.floors)}getInitialFloor(){const e=this.getConfig();return d.selectInitialFloor(this.floors,e.options?.initialFloor)}async setCurrentFloor(e){const t=this.getMap();if(!t)throw new Error("Map is not initialized");this.currentFloor=e,this.log("floor :: setCurrentFloor",{id:e.id,name:e.name,geojsonFeatures:e.geojson?.features?.length??0});const o=this.getConfig(),i=o.options?.wallThickness??1,n=o.options?.boundsPadding??50,r=o.options?.minIndoorZoom??16.5;await d.activateFloor(t,e,{wallFeet:i,updatePOIs:e=>this.updatePoiSource(e),didFit:this.didFit,setDidFit:e=>{this.didFit=e},boundsPadding:n,minIndoorZoom:r,log:(e,t)=>this.log(e,t)})}}const g=c({enabled:!0,prefix:"MinuteMapsSDK"}),h=new Map,y={async getSpriteKeys(e){const t=function(e){if(!e)return;if("string"==typeof e)return e;if(Array.isArray(e)){const t=e[0];if(t&&"string"==typeof t.url)return t.url}if("object"==typeof e&&null!==e){const t=e?.url;if("string"==typeof t)return t}return}(e?.getStyle?.()?.sprite);if(!t||"function"!=typeof fetch)return new Set;const o=t.endsWith(".json")?t:`${t}.json`;if(h.has(o))return h.get(o);try{const e=await fetch(o);if(!e.ok)throw new Error(`Failed to load sprite JSON (${e.status})`);const t=await e.json(),i=new Set(Object.keys(t||{}));return h.set(o,i),i}catch(e){g.warn("sprite fetch failed",o,e);const t=new Set;return h.set(o,t),t}}};const m="units-outline-2d",w=["units-wall-extrusion","units-wall-custom-extrusion"];class b{getMap;is3dEnabled=!0;isUnits2dEnabled=!1;isFlatMode=!1;cachedExtrusionIds=null;extrusionOriginalVisibility=null;unitsExtrusionOriginalVisibility=null;unitsOutlineOriginalVisibility=null;constructor(e){this.getMap=e}onStyleData(){if(this.map){if(this.cachedExtrusionIds=null,!this.is3dEnabled){const e=this.listExtrusionLayerIds();this.setLayersVisibility(e,"none")}this.isUnits2dEnabled&&this.applyUnits2dVisibility(!0)}}set3dEnabled(e){const t=this.map;if(!t)return;const o=this.listExtrusionLayerIds();if(this.cachedExtrusionIds=o,!this.extrusionOriginalVisibility){const e={};o.forEach(o=>{try{const i=t.getLayoutProperty(o,"visibility")||"visible";e[o]=i}catch{e[o]="visible"}}),this.extrusionOriginalVisibility=e}if(e){const e=this.extrusionOriginalVisibility||{};o.forEach(o=>{const i=e[o]??"visible";try{t.getLayer(o)&&t.setLayoutProperty(o,"visibility",i)}catch{}})}else this.setLayersVisibility(o,"none");this.is3dEnabled=e,t.triggerRepaint()}toggle3d(){this.set3dEnabled(!this.is3dEnabled)}getIs3dEnabled(){return this.is3dEnabled}setUnits2dEnabled(e){const t=this.map;t&&(this.applyUnits2dVisibility(e),this.isUnits2dEnabled=e,t.triggerRepaint())}toggleUnits2d(){this.setUnits2dEnabled(!this.isUnits2dEnabled)}getIsUnits2dEnabled(){return this.isUnits2dEnabled}setFlatMode(e){this.map&&(e?(this.set3dEnabled(!1),this.setUnits2dEnabled(!0)):(this.setUnits2dEnabled(!1),this.set3dEnabled(!0)),this.isFlatMode=e)}toggleFlatMode(){this.setFlatMode(!this.isFlatMode)}getIsFlatMode(){return this.isFlatMode}applyUnits2dVisibility(e){const t=this.map;if(t){if(!this.unitsExtrusionOriginalVisibility){const e={};w.forEach(o=>{try{const i=t.getLayoutProperty(o,"visibility")||"visible";e[o]=i}catch{e[o]="visible"}}),this.unitsExtrusionOriginalVisibility=e}if(null==this.unitsOutlineOriginalVisibility)try{const e=t.getLayoutProperty(m,"visibility");this.unitsOutlineOriginalVisibility=e??"none"}catch{this.unitsOutlineOriginalVisibility="none"}if(t.getLayer(m)){const o=e?"visible":this.unitsOutlineOriginalVisibility??"none";try{t.setLayoutProperty(m,"visibility",o)}catch{}}if(e)w.forEach(e=>{if(t.getLayer(e))try{t.setLayoutProperty(e,"visibility","none")}catch{}});else{const e=this.unitsExtrusionOriginalVisibility||{};w.forEach(o=>{const i=e[o]??"visible";if(t.getLayer(o))try{t.setLayoutProperty(o,"visibility",i)}catch{}})}}}listExtrusionLayerIds(){const e=this.map;if(!e)return[];try{const t=e.getStyle(),o=t?.layers||[],i=o.filter(e=>"fill-extrusion"===e?.type).map(e=>e.id),n=Array.isArray(l)?l:[],r=[];return n.forEach(e=>{const t=o.find(t=>t.id===e);t&&"fill-extrusion"===t.type&&r.push(e)}),[...new Set([...i,...r])]}catch{return this.cachedExtrusionIds||[]}}setLayersVisibility(e,t){const o=this.map;o&&e.forEach(e=>{try{o.getLayer(e)&&o.setLayoutProperty(e,"visibility",t)}catch{}})}get map(){return this.getMap()}}function F(e){if(!e)return null;const t=e.getCenter(),o=(e,t=6)=>function(e,t=6){const o=Number(e.toFixed(t));return Object.is(o,-0)?0:o}(e,t);return{center:[o(t.lng),o(t.lat)],zoom:o(e.getZoom(),4),pitch:o(e.getPitch(),2),bearing:o(e.getBearing(),2)}}const x={async updatePOIs(e,t,o){const[n,s]=await Promise.all([o.getAmenities(t.id),o.getDestinations(t.id)]),a=x.buildPOIs(t,n,s,o.spriteKeys);i.setData(e,r,x.toFeatureCollection(a))},buildPOIs(e,t=[],o=[],i){const n=e?.id;if(!n)return[];const r=[];let s=!1;for(const o of t||[]){if(!o.waypoints)continue;const t=C(o),a=A(o.svg,i)||void 0,l="you-are-here";for(const i of o.waypoints||[]){if(i.mapId!==n||!v(i.coordinates))continue;const[u,c]=i.coordinates,d=t&&!s,p=d?l:a,f=i.id??i._?.id;r.push({id:o.id,type:"amenity",name:d?"You are here":o.name||"Amenity",coordinates:[u,c],iconId:p,floorId:e.id,amenityType:o.type,keywords:o.keywords||[],showLabel:!0,isYouAreHere:d,waypointId:f,waypoint:i}),d&&(s=!0)}}for(const t of o||[])if(t.waypoints)for(const o of t.waypoints||[]){if(o.mapId!==n||!v(o.coordinates))continue;const[i,s]=o.coordinates,a=o.id??o._?.id;r.push({id:t.id,type:"destination",name:t.name||"Destination",coordinates:[i,s],floorId:e.id,showLabel:!0,waypointId:a,waypoint:o})}return r},toFeatureCollection:e=>({type:"FeatureCollection",features:e.map(e=>({type:"Feature",geometry:{type:"Point",coordinates:e.coordinates},properties:{id:e.id,name:e.name,poiType:e.type,iconId:e.iconId,floorId:e.floorId,keywords:e.keywords,amenityType:e.amenityType,showLabel:!1!==e.showLabel,isYouAreHere:!0===e.isYouAreHere}}))})};function I(e){return e.find(e=>e.isYouAreHere)||null}function v(e){return Array.isArray(e)&&e.length>=2}function A(e,t){if(!e||!t)return null;const o=/<svg[^>]*\bid\s*=\s*["']([^"']+)["']/i.exec(e),i=o?.[1];return i&&t.has(i)?i:null}function C(e){const t=e=>(e??"").toLowerCase(),o=t(e.name),i=(e.keywords||[]).map(e=>t(e)),n=e.extensors||{},r=t(n.type),s="kiosk"===o||o.includes("kiosk"),a=i.some(e=>e.includes("kiosk"));return s||a||"assistance"===r}class S{deps;routeAnimationFrame=null;routeAnimationStart=null;routeAnimationDurationMs=1200;routeActive=!1;constructor(e){this.deps=e}buildWayfindFeatureCollection(e){if(!e)return this.deps.warn?.("wayfind :: no result"),null;const t=[],o=e=>{if(!e)return;const o=e.coordinates||e.xyz||e._?.coordinates;if(Array.isArray(o)&&o.length>=2){const e=Number(o[0]),i=Number(o[1]);Number.isFinite(e)&&Number.isFinite(i)&&t.push([e,i])}};return Array.isArray(e)?e.length>0&&Array.isArray(e[0]?.points)?e[0].points.forEach(o):e.forEach(o):Array.isArray(e.points)?e.points.forEach(o):Array.isArray(e.path)?e.path.forEach(o):Array.isArray(e.paths?.[0]?.points)&&e.paths[0].points.forEach(o),t.length<2?(this.deps.warn?.("wayfind :: not enough coordinates to draw a route",{resultShape:{isArray:Array.isArray(e),hasPoints:Array.isArray(e.points),hasPath:Array.isArray(e.path),hasPaths0Points:Array.isArray(e.paths?.[0]?.points)},extractedCount:t.length}),null):(this.deps.log?.("wayfind :: extracted coordinates for route",{count:t.length,first:t[0],last:t[t.length-1]}),{type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"LineString",coordinates:t},properties:{}}]})}async wayfindBetweenWaypoints(e,t,o){const n=this.deps.getMap();if(!this.deps.getVenue()||!n)return this.deps.warn?.("wayfindBetweenWaypoints :: venue or map not ready"),null;let r=null;try{r=await this.deps.computeRoute(e,t)}catch(e){return this.deps.warn?.("wayfind :: computeRoute failed",e),null}this.deps.log?.("wayfind :: result",r);const s=this.buildWayfindFeatureCollection(r);if(!s)return r;i.setData(n,a,s),this.deps.log?.("wayfind :: route source updated",{featureCount:s.features.length}),this.startRouteAnimation();const l=o?.centerMode??"route",u=o?.zoom??19;if("none"!==l){const e=s.features[0]?.geometry;if(e&&"LineString"===e.type&&Array.isArray(e.coordinates)){const t=e.coordinates;if("destination"===l){const e=t[t.length-1];n.flyTo({center:e,zoom:u,pitch:45,bearing:0,animate:!0,duration:900})}else if("route"===l){const e=t.map(e=>e[0]),o=t.map(e=>e[1]),i=Math.min(...e),r=Math.max(...e),s=[[i,Math.min(...o)],[r,Math.max(...o)]];n.fitBounds(s,{padding:this.deps.getBoundsPadding(),animate:!0})}}}return r}async navigateFromKioskToDestination(e){const t=this.deps.getMap(),o=this.deps.getVenue();if(!t||!o)return null;const i=this.deps.getYouAreHerePOI();if(!i||!i.waypoint)return this.deps.warn?.("navigateFromKioskToDestination :: no you-are-here waypoint available",i),null;const n=e.waypoint||e.waypoints?.[0];if(!n)return this.deps.warn?.("navigateFromKioskToDestination :: destination has no waypoint",e),null;this.deps.log?.("navigateFromKioskToDestination :: from kiosk to destination",{kioskWaypoint:i.waypoint,destWaypoint:n});const r=this.deps.getYouAreHereCoordinates()??i.waypoint?.coordinates,s=n.coordinates||n.xyz||n._?.coordinates,a=Array.isArray(s)&&s.length>=2?[Number(s[0]),Number(s[1])]:null;return r&&a?this.showRouteContext(r,a):this.deps.warn?.("navigateFromKioskToDestination :: could not derive endpoint coordinates",{fromCoords:r,rawDest:s}),this.wayfindBetweenWaypoints(i.waypoint,n,{centerMode:"route"})}clearRoute(){const e=this.deps.getMap();if(!e)return;this.stopRouteAnimation();i.setData(e,a,{type:"FeatureCollection",features:[]}),this.deps.log?.("wayfind :: route cleared")}setPoiLayersVisible(e){const t=this.deps.getMap();if(!t)return;const o=e?"visible":"none";["poi-accessibility-icons","poi-destination-circles","poi-destination-labels","poi-entrance-exit-icons","poi-parking-icons","poi-other-amenity-icons"].forEach(e=>{t.getLayer(e)&&t.setLayoutProperty(e,"visibility",o)})}updateRouteEndpoints(e,t){const o=this.deps.getMap();if(!o)return;const i=o.getSource("route-endpoints");if(!i)return;const n={type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"Point",coordinates:e},properties:{role:"source"}},{type:"Feature",geometry:{type:"Point",coordinates:t},properties:{role:"destination"}}]};i.setData(n)}clearRouteEndpoints(){const e=this.deps.getMap();if(!e)return;const t=e.getSource("route-endpoints");if(!t)return;t.setData({type:"FeatureCollection",features:[]})}showRouteContext(e,t){this.updateRouteEndpoints(e,t)}hideRouteContext(){this.setPoiLayersVisible(!0),this.clearRouteEndpoints()}startRouteAnimation(){if(!this.deps.getMap())return;if("undefined"==typeof window)return;null!=this.routeAnimationFrame&&(cancelAnimationFrame(this.routeAnimationFrame),this.routeAnimationFrame=null),this.routeAnimationStart=performance.now(),this.routeActive=!0;const e=this.deps.debug,t=o=>{const i=this.deps.getMap();if(!i||!this.routeActive||null==this.routeAnimationStart)return;const n=o-this.routeAnimationStart,r=Math.min(1,n/this.routeAnimationDurationMs),s=Math.max(.001,r);e&&this.deps.log?.("route animation frame",{t:r,clamped:s});const a=Math.max(0,s-.01),l=Math.min(1,s+.01),u=["interpolate",["linear"],["line-progress"],0,"rgba(0,122,255,1.0)",a,"rgba(0,122,255,1.0)",l,"rgba(0,122,255,0.0)",1,"rgba(0,122,255,0.0)"],c=["interpolate",["linear"],["line-progress"],0,"rgba(255,255,255,0.7)",a,"rgba(255,255,255,0.7)",l,"rgba(255,255,255,0.0)",1,"rgba(255,255,255,0.0)"];i.getLayer("route-line")&&i.setPaintProperty("route-line","line-gradient",u),i.getLayer("route-halo")&&i.setPaintProperty("route-halo","line-gradient",c),this.routeAnimationFrame=r<1?requestAnimationFrame(t):null};this.routeAnimationFrame=requestAnimationFrame(t)}stopRouteAnimation(){this.routeActive=!1,null!=this.routeAnimationFrame&&"undefined"!=typeof window&&cancelAnimationFrame(this.routeAnimationFrame),this.routeAnimationFrame=null,this.routeAnimationStart=null;const e=this.deps.getMap();e&&(e.getLayer("route-line")&&(e.setPaintProperty("route-line","line-gradient",void 0),e.setPaintProperty("route-line","line-color","#007aff")),e.getLayer("route-halo")&&(e.setPaintProperty("route-halo","line-gradient",void 0),e.setPaintProperty("route-halo","line-color","#ffffff")))}}class E{getVenue;getFloors;getFloorById;logFn;constructor(e){this.getVenue=e.getVenue,this.getFloors=e.getFloors,this.getFloorById=e.getFloorById,this.logFn=e.log}get venue(){return this.getVenue()}log(...e){this.logFn&&this.logFn(...e)}loadForFloor(e){if(!e||!this.venue)return[];try{const t=this.venue.amenities?.getByMap(e.id)||[];return Array.isArray(t)?t.map(t=>{const o=t;return o.floorId=e.id,o}):[]}catch{return[]}}getAll(){return this.getFloors().flatMap(e=>this.loadForFloor(e))}getByFloorId(e){const t=this.getFloorById(e);return t?this.loadForFloor(t):[]}getAllKiosks(){return this.getAll().filter(e=>C(e))}getKioskForFloor(e){const t=this.getFloorById(e);if(!t)return null;return this.loadForFloor(t).find(e=>C(e))??null}logKioskForFloor(e){const t=this.getFloorById(e);if(!t)return;const o=this.getKioskForFloor(e);o?this.log("amenity :: kiosk found",{floorId:t.id,id:o.id,name:o.name,keywords:o.keywords,waypoints:o.waypoints,raw:o}):this.log("amenity :: kiosk not found on floor",{floorId:t.id})}}c({enabled:!0,prefix:"MinuteMapsSDK"});class M{mode;proxyBaseUrl;direct;fetchImpl;tokenCache=null;constructor(e){const t="undefined"!=typeof window?window:globalThis,o=e.fetchImpl??t.fetch;if("function"!=typeof o)throw new Error("Fetch API is not available in this environment");this.fetchImpl=o.bind(t),this.mode=e.mode,this.proxyBaseUrl=("proxy"===e.mode?e.proxyBaseUrl:void 0)||"/api/jacs","direct"===e.mode?this.direct={host:this.normalizeHost(e.host),clientId:e.clientId,username:e.username,password:e.password}:this.direct=null}async getPolygonLayers(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/polygon-layer`,o=await this.getJson(t);return this.extractArray(o)}async getFloorMapTemplate3d(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/building/${encodeURIComponent(String(e.buildingId))}/floor/${encodeURIComponent(String(e.floorId))}/map-template/3d`,o=await this.getJson(t);return this.extractArray(o)}async getFloors(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/building/${encodeURIComponent(String(e.buildingId))}/floor`,o=await this.getJson(t);return this.extractArray(o)}async getVenue(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}`,o=await this.getJson(t),i=o?.venue||o?.data||o;if(!i||"object"!=typeof i)throw new Error("JACS venue response was not a JSON object");return i}async getFloorMapGeojson(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/building/${encodeURIComponent(String(e.buildingId))}/floor/${encodeURIComponent(String(e.floorId))}/map/geojson`,o=await this.getJson(t),i=o?.geojson||o?.data||o;if(!i||"FeatureCollection"!==i.type||!Array.isArray(i.features))throw new Error("JACS floor geojson did not look like a GeoJSON FeatureCollection");return i}async getBuildingFull(e){const t=new URLSearchParams;t.set("mapProfile",String(e.mapProfile??"public")),t.set("geojson",String(e.geojson??!0));const o=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/building/${encodeURIComponent(String(e.buildingId))}/full?${t.toString()}`,i=await this.getJson(o),n=i?.data||i?.result||i;if(!n||"object"!=typeof n)throw new Error("JACS building full response was not a JSON object");return n}async getDestinations(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/destination`,o=await this.getJson(t);return this.extractArray(o)}async getAmenities(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/amenity`,o=await this.getJson(t);return this.extractArray(o)}async getBuildings(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/building`,o=await this.getJson(t);return this.extractArray(o)}async getStylesheet3d(e){const t=`/customer/${encodeURIComponent(String(e.customerId))}/venue/${encodeURIComponent(String(e.venueId))}/building/${encodeURIComponent(String(e.buildingId))}/stylesheet/3d`,o=await this.getJson(t),i=o?.style||o?.data||o;if(!i||"object"!=typeof i)throw new Error("JACS stylesheet response was not a JSON object");return i}invalidateToken(){this.tokenCache=null}async getJson(e){if("proxy"===this.mode){const t=this.proxyBaseUrl.replace(/\/+$/,""),o=e.startsWith("/")?e:`/${e}`,i=await this.fetchImpl(`${t}${o}`,{method:"GET",headers:{Accept:"application/json"}});if(!i.ok){const e=await this.safeReadText(i);throw new Error(`JACS proxy GET failed (${i.status} ${i.statusText}) :: ${e}`)}return await i.json()}const t=this.direct;if(!t)throw new Error("JacsProvider is not configured for direct mode");const o=await this.getJwtToken(),i=this.joinUrl(t.host,e),n=await this.fetchImpl(i,{method:"GET",headers:{Authorization:`Bearer ${o}`,Accept:"application/json"}});if(!n.ok){const e=await this.safeReadText(n);throw new Error(`JACS GET failed (${n.status} ${n.statusText}) :: ${e}`)}return await n.json()}extractArray(e){return(Array.isArray(e)?e:null)||(Array.isArray(e?.data)?e.data:null)||(Array.isArray(e?.items)?e.items:null)||(Array.isArray(e?.results)?e.results:null)||[]}async getJwtToken(){const e=this.direct;if(!e)throw new Error("getJwtToken should not be called in proxy mode");const t=Date.now(),o=this.tokenCache;if(o?.token&&t<o.expiresAtMs-3e4)return o.token;const i=this.joinUrl(e.host,"/auth/token"),n=new URLSearchParams;n.set("grant_type","password"),n.set("client_id",e.clientId),n.set("username",e.username),n.set("password",e.password);const r=await this.fetchImpl(i,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:n.toString()});if(!r.ok){const e=await this.safeReadText(r);throw new Error(`JACS auth failed (${r.status} ${r.statusText}) :: ${e}`)}const s=await r.json(),a=s?.access_token||s?.token||s?.jwt||s?.accessToken;if(!a)throw new Error("JACS auth response did not contain a token");const l=s?.expires_in??s?.expiresIn??s?.expires??s?.ttl,u="number"==typeof l?l:Number(l),c=Number.isFinite(u)&&u>0?u:600;return this.tokenCache={token:a,expiresAtMs:Date.now()+1e3*c},a}normalizeHost(e){return String(e||"").replace(/\/+$/,"")}joinUrl(e,t){const o=this.normalizeHost(e),i=String(t||"");return i?`${o}${i.startsWith("/")?"":"/"}${i}`:o}async safeReadText(e){try{return await e.text()}catch{return""}}}const B=c({enabled:!0,prefix:"MinuteMapsSDK jacs"});class k{config;jacs;floors=[];buildingId=null;destinationsByMapId=new Map;amenitiesByMapId=new Map;venueLike=null;async init(e){this.config=e;const t=e.jacs;if(!t?.mode)throw new Error("config.jacs.mode is required");if("proxy"!==t.mode){if(!t.host)throw new Error("config.jacs.host is required (direct mode)");if(!t.auth?.clientId)throw new Error("config.jacs.auth.clientId is required (direct mode)");if(!t.auth?.username)throw new Error("config.jacs.auth.username is required (direct mode)");if(!t.auth?.password)throw new Error("config.jacs.auth.password is required (direct mode)");this.jacs=new M({mode:"direct",host:t.host,clientId:t.auth.clientId,username:t.auth.username,password:t.auth.password})}else this.jacs=new M({mode:"proxy",proxyBaseUrl:t.proxyBaseUrl||"/api/jacs"})}async loadVenue(){const e=this.config.jmap.customerId,t=this.config.jmap.venueId;if(null==e)throw new Error("config.jmap.customerId is required");if(null==t)throw new Error("config.jmap.venueId is required");const o=await this.jacs.getBuildings({customerId:e,venueId:t}),i=o[0]?.id??o[0]?.buildingId;if(0===o.length||!i)throw new Error("No buildings found for this customer and venue");const[n,r]=await Promise.all([this.jacs.getVenue({customerId:e,venueId:t}),this.jacs.getBuildingFull({customerId:e,venueId:t,buildingId:i,mapProfile:"public",geojson:!0})]);this.buildingId=i;const s=(r?.floors?.items??r?.floors??[]).map(e=>{const t=e.map??{};return{id:e.id,name:e.name??e.shortName??String(e.id),sequence:e.level??e.preference,isDefault:e.id===r?.defaultFloorId,geojson:t.geojson??null,mapTemplate3d:[],_waypoints:t.waypoints?.items??[]}});this.floors=s;let a=[],l=[];try{const o=await this.jacs.getJson(`/customer/${e}/venue/${t}/full?mapProfile=public`);a=o?.destinations?.items??[],l=o?.amenities?.items??[]}catch{try{a=await this.jacs.getDestinations({customerId:e,venueId:t})}catch{}try{l=await this.jacs.getAmenities({customerId:e,venueId:t})}catch{}}this.amenitiesByMapId.clear();for(const e of l)for(const t of e?.waypoints??[]){const o=t?.mapId;if(null==o)continue;const i=this.amenitiesByMapId.get(o)??[];i.push(e),this.amenitiesByMapId.set(o,i)}this.destinationsByMapId.clear();for(const e of a)for(const t of e?.waypoints??[]){const o=t?.mapId;if(null==o)continue;const i=this.destinationsByMapId.get(o)??[];i.push(e),this.destinationsByMapId.set(o,i)}return this.venueLike={...n,floors:s,polygonLayers:[],destinations:{items:[...a],getByMap:({id:e})=>this.destinationsByMapId.get(e)??[]},amenities:{items:[...l],getByMap:({id:e})=>this.amenitiesByMapId.get(e)??[]},buildings:{items:[...o],getAllFloors:()=>this.floors},styleSheet:null},this.venueLike}async ensureFloorGeojson(e){if(e.geojson)return;const t=this.config.jmap.customerId,o=this.config.jmap.venueId;try{const i=await this.jacs.getFloorMapGeojson({customerId:t,venueId:o,buildingId:this.buildingId,floorId:e.id});e.geojson=function(e){return(e?.type?e:e?.data)??null}(i)}catch(t){B.warn("floor geojson fetch failed",{floorId:e.id,e:t})}}async preloadRemainingFloors(){const e=this.floors.filter(e=>!e.geojson);0!==e.length&&(await Promise.all(e.map(e=>this.ensureFloorGeojson(e))),B.debug("preloaded geojson for remaining floors",{count:e.length}))}async getFloors(){return this.floors}async getAmenities(e){return this.amenitiesByMapId.get(e)??[]}async getDestinations(e){return this.destinationsByMapId.get(e)??[]}}class z{handlers=new Map;on(e,t){this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e).add(t)}off(e,t){t?this.handlers.get(e)?.delete(t):this.handlers.delete(e)}emit(e,t){this.handlers.get(e)?.forEach(e=>{try{e(t)}catch{}})}}var j={version:8,name:"Hospital Indoor Mapping - Hybrid Style Healthcare Compliant",metadata:{description:"Accessibility-focused hospital navigation with proper healthcare standards",author:"Hospital Mapping Team",version:"7.1.0"},sprite:"http://localhost:4000/sprites/sprite",glyphs:"https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",sources:{"osm-tiles":{type:"raster",tiles:["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],tileSize:256,attribution:"© OpenStreetMap contributors"},"indoor-data":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"poi-data":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"accessibility-data":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"unit-walls":{type:"geojson",data:{type:"FeatureCollection",features:[]}},"route-data":{type:"geojson",data:{type:"FeatureCollection",features:[]},lineMetrics:!0},"route-endpoints":{type:"geojson",data:{type:"FeatureCollection",features:[]}}},layers:[{id:"background",type:"background",paint:{"background-color":"#F5F5F5"}},{id:"osm",type:"raster",source:"osm-tiles",minzoom:0,paint:{"raster-opacity":["interpolate",["linear"],["zoom"],14,.8,16,.6,18,.4]}},{id:"pattern-water",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Water"],paint:{"fill-color":"#5DADE2","fill-opacity":.6}},{id:"pattern-grass",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Grass"],paint:{"fill-color":"#7CB342","fill-opacity":.5}},{id:"pattern-trees",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Trees"],paint:{"fill-color":"#4CAF50","fill-opacity":.4}},{id:"pattern-pavement",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Pavement"],paint:{"fill-color":"#E0E0E0","fill-opacity":.6}},{id:"pattern-outdoor-terrace",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-OutdoorTerrace"],paint:{"fill-color":"#8D6E63","fill-opacity":.3}},{id:"parking-lots",type:"fill",source:"indoor-data",filter:["==",["get","featureType"],"Parking-Lots"],paint:{"fill-color":"#BDBDBD","fill-opacity":.6}},{id:"parking-lots-outline",type:"line",source:"indoor-data",filter:["==",["get","featureType"],"Parking-Lots"],paint:{"line-color":"#757575","line-width":1,"line-dasharray":[3,2]}},{id:"boundary-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],paint:{"fill-color":"#FAF3E2","fill-opacity":1}},{id:"building-roof-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],paint:{"fill-color":"#162e51","fill-opacity":1}},{id:"corridors-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["any",["==",["get","featureType"],"Corridors"],["==",["get","featureType"],"Corridor"]],paint:{"fill-color":"#F0E6D1"}},{id:"accessible-routes",type:"line",source:"accessibility-data",minzoom:16.5,filter:["==",["get","accessible"],!0],paint:{"line-color":"#2E7D32","line-width":["interpolate",["linear"],["zoom"],15,2,18,3,20,4],"line-dasharray":[.5,1],"line-opacity":.7}},{id:"units-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Units"],paint:{"fill-color":["case",["has","category"],["match",["get","category"],"healthcare","#7C3AED","emergency","#DC2626","diagnostic","#0EA5E9","surgical","#7C3AED","retail","#FF6B6B","fnb","#FFA500","admin","#A29BFE","amenities","#48C9B0","staff","#74B9FF","security","#1A7A96","waiting","#E1BEE7","#8ecae6"],"#8ecae6"],"fill-opacity":["interpolate",["linear"],["zoom"],15,.85,17,.92,19,.95]}},{id:"units-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Units"],layout:{visibility:"none","line-join":"round","line-cap":"round"},paint:{"line-color":"#162e51","line-opacity":.9,"line-width":["interpolate",["linear"],["zoom"],16,.8,18,1.4,20,2.2]}},{id:"backofhouse-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],paint:{"fill-color":"#D6D6CC","fill-opacity":.7}},{id:"backofhouse-pattern",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],paint:{"line-color":"#90A4AE","line-width":.5,"line-opacity":.4}},{id:"backofhouse-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#7B8D93","line-width":["interpolate",["linear"],["zoom"],16,.6,18,1,20,1.4],"line-opacity":.9}},{id:"restrooms-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Restrooms"],paint:{"fill-color":"#5B8468","fill-opacity":1}},{id:"restrooms-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Restrooms"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#3F5D4A","line-width":["interpolate",["linear"],["zoom"],16,.6,18,1,20,1.4],"line-opacity":.9}},{id:"obstacles-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Obstacles"],paint:{"fill-color":"#E8E9ED","fill-opacity":.85}},{id:"obstacles-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Obstacles"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#B0B1B5","line-width":["interpolate",["linear"],["zoom"],16,.5,18,.9,20,1.2],"line-opacity":.9}},{id:"escalators-stairs-elevators",type:"fill",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Escalators","Stairs","Elevators"]]],paint:{"fill-color":"#6A8799","fill-opacity":1}},{id:"escalators-stairs-elevators-outline-2d",type:"line",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Escalators","Stairs","Elevators"]]],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#455A64","line-width":["interpolate",["linear"],["zoom"],16,.6,18,1,20,1.4],"line-opacity":.9}},{id:"exits-doors",type:"fill",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Exits","Doors","Exit","Door"]]],paint:{"fill-color":"#4CAF50","fill-opacity":.6}},{id:"kiosks-fill",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Kiosks"],paint:{"fill-color":"#9C27B0","fill-opacity":.7}},{id:"pattern-lounge",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-Lounge"],paint:{"fill-color":"#CE93D8","fill-opacity":.5}},{id:"pattern-indoor-foodcourt",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Pattern-IndoorFoodcourt"],paint:{"fill-color":"#FFCC80","fill-opacity":.6}},{id:"corridors-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["any",["==",["get","featureType"],"Corridors"],["==",["get","featureType"],"Corridor"]],paint:{"line-color":"#BCAAA4","line-width":["interpolate",["linear"],["zoom"],15,.5,18,1,20,1.5]}},{id:"boundary-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],paint:{"line-color":"#263238","line-width":["interpolate",["linear"],["zoom"],12,2,15,2.5,18,3,20,3.5],"line-opacity":["interpolate",["linear"],["zoom"],12,.7,17,.85,18,1]}},{id:"building-roof-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Boundary"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#face00","line-width":["interpolate",["linear"],["zoom"],15,1.6,18,2.4,20,3.2],"line-opacity":.95}},{id:"interior-parking-lots",type:"fill",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Interior-ParkingLots"],paint:{"fill-color":"#757575","fill-opacity":.8}},{id:"interior-parking-lots-outline",type:"line",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Interior-ParkingLots"],paint:{"line-color":"#616161","line-width":1.5}},{id:"building-extrusion",type:"fill-extrusion",source:"indoor-data",filter:["==",["get","featureType"],"Boundary"],maxzoom:16.5,paint:{"fill-extrusion-color":"#162e51","fill-extrusion-height":15,"fill-extrusion-base":0,"fill-extrusion-opacity":1}},{id:"units-wall-extrusion",type:"fill-extrusion",source:"unit-walls",minzoom:16.5,filter:["all",["==",["get","featureType"],"UnitWalls"],["!",["has","custom_height"]]],paint:{"fill-extrusion-color":["case",["has","category"],["match",["get","category"],"healthcare","#5B2DB8","emergency","#B91C1C","diagnostic","#0C7FAB","surgical","#5B2DB8","retail","#CC5555","fnb","#CC8400","admin","#7B73CC","amenities","#3A9B88","staff","#5C96CC","security","#135C75","waiting","#B894C2","#eeeeee"],"#eeeeee"],"fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-vertical-gradient":!1,"fill-extrusion-opacity":.9}},{id:"units-wall-custom-extrusion",type:"fill-extrusion",source:"unit-walls",minzoom:16.5,filter:["has","custom_height"],paint:{"fill-extrusion-color":["case",["has","category"],["match",["get","category"],"healthcare","#5B2DB8","emergency","#B91C1C","diagnostic","#0C7FAB","surgical","#5B2DB8","retail","#CC5555","fnb","#CC8400","admin","#7B73CC","amenities","#3A9B88","staff","#5C96CC","security","#135C75","waiting","#B894C2","#FDFAF2"],"#FDFAF2"],"fill-extrusion-height":["to-number",["get","custom_height"]],"fill-extrusion-base":0,"fill-extrusion-vertical-gradient":!1,"fill-extrusion-opacity":.95}},{id:"corridors-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["any",["==",["get","featureType"],"Corridors"],["==",["get","featureType"],"Corridor"]],layout:{visibility:"none"},paint:{"fill-extrusion-color":"#FFF8E1","fill-extrusion-height":["step",["zoom"],0,18,3.2],"fill-extrusion-base":0,"fill-extrusion-opacity":["step",["zoom"],0,18,.85]}},{id:"backofhouse-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Back-of-house"],paint:{"fill-extrusion-color":"#D6D6CC","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-opacity":1}},{id:"restrooms-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Restrooms"],paint:{"fill-extrusion-color":"#5B8468","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-opacity":.9}},{id:"obstacles-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Obstacles"],paint:{"fill-extrusion-color":"#E8E9ED","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,.8,17.5,1.5,18.2,2],"fill-extrusion-base":0,"fill-extrusion-opacity":1}},{id:"escalators-stairs-elevators-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["in",["get","featureType"],["literal",["Escalators","Stairs","Elevators"]]],paint:{"fill-extrusion-color":"#6A8799","fill-extrusion-height":["interpolate",["linear"],["zoom"],15.5,0,16.5,2,17.5,3,18.2,3.2],"fill-extrusion-base":0,"fill-extrusion-vertical-gradient":!0,"fill-extrusion-opacity":.9}},{id:"interior-parking-extrusion",type:"fill-extrusion",source:"indoor-data",minzoom:16.5,filter:["==",["get","featureType"],"Interior-ParkingLots"],paint:{"fill-extrusion-color":"#757575","fill-extrusion-height":["interpolate",["linear"],["zoom"],15,0,16,2,17,3,18,4],"fill-extrusion-base":0,"fill-extrusion-opacity":.85}},{id:"route-line",type:"line",source:"route-data",minzoom:16.5,layout:{"line-cap":"round","line-join":"round"},paint:{"line-color":"#007aff","line-width":["interpolate",["linear"],["zoom"],16.5,3,18,5,20,7],"line-opacity":.9}},{id:"route-halo",type:"line",source:"route-data",minzoom:16.5,paint:{"line-color":"white","line-width":["interpolate",["linear"],["zoom"],16.5,5,18,7,20,9],"line-opacity":.7}},{id:"route-endpoint-source",type:"circle",source:"route-endpoints",minzoom:16.5,filter:["==",["get","role"],"source"],paint:{"circle-radius":6,"circle-color":"#ffffff","circle-stroke-width":3,"circle-stroke-color":"#007aff","circle-opacity":1}},{id:"route-endpoint-destination",type:"circle",source:"route-endpoints",minzoom:16.5,filter:["==",["get","role"],"destination"],paint:{"circle-radius":7,"circle-color":"#007aff","circle-stroke-width":3,"circle-stroke-color":"#ffffff","circle-opacity":1}},{id:"poi-accessibility-icons",type:"symbol",source:"poi-data",filter:["==",["get","accessible"],!0],minzoom:16.5,layout:{"icon-image":"wheelchair-accessible","icon-size":["interpolate",["linear"],["zoom"],15,.4,17,.6,19,.8],"icon-allow-overlap":!1,"icon-padding":4}},{id:"poi-destination-circles",type:"circle",source:"poi-data",filter:["==",["get","poiType"],"destination"],minzoom:16.5,paint:{"circle-radius":["interpolate",["linear"],["zoom"],15,3,17,4,19,5,20,6],"circle-color":"#162e51","circle-stroke-width":2,"circle-stroke-color":"#FFFFFF","circle-opacity":.9}},{id:"poi-destination-labels",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"destination"],["==",["get","showLabel"],!0]],minzoom:18.5,layout:{"text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],18.5,12,20,14],"text-offset":[0,.8],"text-anchor":"top","text-font":["Noto Sans Bold"],"text-max-width":12,"text-allow-overlap":!1,"text-rotation-alignment":"viewport"},paint:{"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1}},{id:"poi-entrance-exit-icons",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"amenity"],["any",["!=",["index-of","entrance",["get","keywords"]],-1],["!=",["index-of","exit",["get","keywords"]],-1],["!=",["index-of","door",["get","keywords"]],-1]]],minzoom:15,layout:{"icon-image":["get","iconId"],"icon-size":["interpolate",["linear"],["zoom"],16.5,.5,18,.6,20,.8],"icon-allow-overlap":!0,"icon-padding":2,"icon-optional":!1,"icon-rotation-alignment":"viewport","icon-pitch-alignment":"viewport","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],16.5,0,18.5,0,19,12,20,13],"text-offset":[0,1.3],"text-anchor":"top","text-optional":!0,"text-padding":4,"text-font":["Noto Sans Bold"],"text-rotation-alignment":"viewport"},paint:{"icon-halo-color":"#FFFFFF","icon-halo-width":1.5,"icon-halo-blur":.5,"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1,"icon-translate":[0,-20],"icon-translate-anchor":"viewport"}},{id:"poi-parking-icons",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"amenity"],["any",["!=",["index-of","parking",["get","keywords"]],-1],["!=",["index-of","park",["get","keywords"]],-1]]],minzoom:14,layout:{"icon-image":["get","iconId"],"icon-size":["interpolate",["linear"],["zoom"],16.5,.5,18,.6,20,.8],"icon-allow-overlap":!0,"icon-padding":2,"icon-optional":!1,"icon-rotation-alignment":"viewport","icon-pitch-alignment":"viewport","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],16.5,0,18.5,0,19,12,20,13],"text-offset":[0,1.3],"text-anchor":"top","text-optional":!0,"text-padding":4,"text-font":["Noto Sans Bold"],"text-rotation-alignment":"viewport"},paint:{"icon-halo-color":"#FFFFFF","icon-halo-width":1.5,"icon-halo-blur":.5,"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1,"icon-translate":[0,-20],"icon-translate-anchor":"viewport"}},{id:"poi-other-amenity-icons",type:"symbol",source:"poi-data",filter:["all",["==",["get","poiType"],"amenity"],["==",["index-of","entrance",["get","keywords"]],-1],["==",["index-of","exit",["get","keywords"]],-1],["==",["index-of","door",["get","keywords"]],-1],["==",["index-of","parking",["get","keywords"]],-1],["==",["index-of","park",["get","keywords"]],-1]],minzoom:17.5,layout:{"icon-image":["get","iconId"],"icon-size":["interpolate",["linear"],["zoom"],17.5,.5,18,.6,20,.8],"icon-allow-overlap":!0,"icon-padding":2,"icon-optional":!1,"icon-rotation-alignment":"viewport","icon-pitch-alignment":"viewport","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],17.5,0,18.5,0,19,12,20,13],"text-offset":[0,1.3],"text-anchor":"top","text-optional":!0,"text-padding":4,"text-font":["Noto Sans Bold"],"text-rotation-alignment":"viewport"},paint:{"icon-halo-color":"#FFFFFF","icon-halo-width":1.5,"icon-halo-blur":.5,"text-color":"#242930","text-halo-color":"#FFFFFF","text-halo-width":1.5,"text-halo-blur":1,"icon-translate":[0,-20],"icon-translate-anchor":"viewport"}},{id:"poi-you-are-here",type:"symbol",source:"poi-data",filter:["==",["get","isYouAreHere"],!0],minzoom:16.5,layout:{"icon-image":["coalesce",["get","iconId"],"you-are-here"],"icon-size":["interpolate",["linear"],["zoom"],16.5,.8,18,1,20,1.2],"icon-allow-overlap":!0,"icon-ignore-placement":!0,"icon-anchor":"bottom","text-field":["get","name"],"text-size":["interpolate",["linear"],["zoom"],17.5,11,19.5,13],"text-offset":[0,1.2],"text-anchor":"top","text-font":["Noto Sans Bold"],"text-optional":!0},paint:{"text-color":"#ffffff","text-halo-color":"#000000","text-halo-width":1.5,"text-halo-blur":.8}}]};function P(e,t,o={}){e.sources||={},e.sources[t]||(e.sources[t]={type:"geojson",data:{type:"FeatureCollection",features:[]},...o})}function T(e){let t=structuredClone(e.style);if(t.sprite=e.customSprite||t.sprite||e.defaultSpriteUrl,P(t,n),P(t,s),P(t,r),P(t,a,{lineMetrics:!0}),P(t,"route-endpoints"),e.floorLayers)for(const o of Object.keys(e.floorLayers))P(t,`amenity_${o}`),P(t,`destination_${o}`),P(t,`pathTypes_${o}`);return t}const D="https://demotiles.maplibre.org/styles/osm-bright-gl-style/sprite";class L{config;map=null;data=new k;wayfindingProvider={wayfindBetweenWaypoints:async()=>{throw new Error("Wayfinding is not yet implemented in the SDK")}};events=new z;floorsApi;venue=null;spriteKeys=null;debug;logger;defaultCamera=null;viewModes;amenityManager;wayfinding;constructor(e){this.config=e,this.debug=Boolean(e.debug??e.options?.debug),this.logger=c({enabled:this.debug,prefix:"MinuteMapsSDK"}),this.viewModes=new b(()=>this.map),this.floorsApi=new f({getMap:()=>this.map,getConfig:()=>this.config,updatePoiSource:async e=>{const t=this.map;if(!t)return;const o=this.getAllPOIs(e),n=x.toFeatureCollection(o);i.setData(t,r,n)},log:(...e)=>this.logger.debug(...e)}),this.amenityManager=new E({getVenue:()=>this.venue,getFloors:()=>this.floorsApi.getFloors(),getFloorById:e=>this.floorsApi.getFloors().find(t=>t.id===e)??null,log:(...e)=>this.logger.debug(...e)}),this.wayfinding=new S({getMap:()=>this.map,getVenue:()=>this.venue,getYouAreHerePOI:e=>this.getYouAreHerePOI(e),getYouAreHereCoordinates:e=>this.getYouAreHereCoordinates(e),getBoundsPadding:()=>this.getBoundsPadding(),computeRoute:async(e,t)=>{const o=this.config.jmap.customerId,i=this.config.jmap.venueId;if(null==o)throw new Error("config.jmap.customerId is required");if(null==i)throw new Error("config.jmap.venueId is required");return this.wayfindingProvider.wayfindBetweenWaypoints({customerId:o,venueId:i,from:e,to:t})},log:(...e)=>this.logger.debug(...e),warn:(...e)=>this.logger.warn(...e),debug:this.debug})}async init(){const{venueId:t,customerId:o}=this.config?.jmap;if(null==t||null==o)throw new Error("config.jmap.customerId and config.jmap.venueId are required");if(!this.config.container)throw new Error("config.container is required (HTMLElement or element id)");this.logger.debug("init :: starting (JACS)",{venueId:t,customerId:o});try{await this.data.init(this.config),this.logger.debug("providers :: JACS ready"),this.venue=await this.data.loadVenue(),this.logger.debug("JACS :: venue loaded",this.venue.id),this.floorsApi.setFloors(this.venue.floors),this.logger.debug("JACS :: floors loaded",{count:this.venue.floors.length});const t=T({style:j,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:D});this.ensureFloorLayersFromStyle(t),this.map=function(t,o){const i="string"==typeof t?document.getElementById(t):t;if(!i)throw new Error("Map container not found");return new e.Map({container:i,style:o,center:[0,0],zoom:16,pitch:45,bearing:0})}(this.config.container,t),await new Promise(e=>this.map.once("load",()=>e())),this.map.on("error",e=>{const t=e?.error?.message||e?.message||e;this.logger.error("map :: error",{msg:t,sourceId:e?.sourceId,tile:e?.tile})}),this.map.on("styledata",()=>{try{this.viewModes.onStyleData()}catch{}}),this.map.on("move",()=>{if(!this.map)return;const e=F(this.map);e&&this.events.emit("cameraChange",{camera:e})}),this.ensureCoreSources(),this.spriteKeys=await y.getSpriteKeys(this.map);const o=this.floorsApi.getInitialFloor();Boolean(o?.geojson?.features?.length)||this.applyInitialViewFromVenue(),o&&await this.setCurrentFloor(o),this.defaultCamera=F(this.map),this.events.emit("ready",{venue:this.venue}),this.events.emit("floorsLoaded",{})}catch(e){throw this.logger.error("init :: failed (JACS)",e),this.events.emit("error",{error:e}),e}}on(e,t){this.events.on(e,t)}off(e,t){this.events.off(e,t)}addControl(e,t){this.map?.addControl(e,t)}setView(e){!function(e,t){if(!e)return;const{center:o,zoom:i,pitch:n,bearing:r,animate:s,duration:a}=t;if(s){const t=e.getCenter(),s=o||[t.lng,t.lat],l=i??e.getZoom(),u=n??e.getPitch(),c=r??e.getBearing(),d="number"==typeof a?a:900;return void e.flyTo({center:s,zoom:l,pitch:u,bearing:c,duration:d,essential:!0})}o&&e.setCenter(o),void 0!==i&&e.setZoom(i),void 0!==n&&e.setPitch(n),void 0!==r&&e.setBearing(r)}(this.map,e)}get amenities(){return this.amenityManager}resetView(e){!function(e,t,o){if(!e||!t)return;const{center:i,zoom:n,pitch:r,bearing:s}=t,a=Boolean(o?.animate),l="number"==typeof o?.duration?o.duration:800;a?e.easeTo({center:i,zoom:n,pitch:r,bearing:s,duration:l}):e.jumpTo({center:i,zoom:n,pitch:r,bearing:s})}(this.map,this.defaultCamera,e)}set3dEnabled(e){this.viewModes.set3dEnabled(e)}toggle3d(){this.viewModes.toggle3d()}getIs3dEnabled(){return this.viewModes.getIs3dEnabled()}setUnits2dEnabled(e){this.viewModes.setUnits2dEnabled(e)}toggleUnits2d(){this.viewModes.toggleUnits2d()}getIsUnits2dEnabled(){return this.viewModes.getIsUnits2dEnabled()}setFlatMode(e){this.viewModes.setFlatMode(e)}toggleFlatMode(){this.viewModes.toggleFlatMode()}getIsFlatMode(){return this.viewModes.getIsFlatMode()}getFloors(){return this.floorsApi.getFloors()}getCurrentFloor(){return this.floorsApi.getCurrentFloor()}getDefaultFloor(){return this.floorsApi.getDefaultFloor()}getDestinations(e){const t=e||this.getCurrentFloor();return function(e,t){if(!e||!t)return[];try{const o=e.destinations?.getByMap?.({id:t.id})||[];return Array.isArray(o)?o:[]}catch{return[]}}(this.venue,t)}getPolygonLayers(){return this.venue?.polygonLayers??[]}getFloorMapTemplate3d(e){return this.venue?.mapTemplates3d?.[String(e)]??[]}getAllPOIs(e){const t=e||this.getCurrentFloor();if(!t)return[];return function(e,t,o,i){return x.buildPOIs(e,t,o,i)}(t,this.amenityManager.getByFloorId(t.id),this.getDestinations(t),this.spriteKeys)}getYouAreHerePOI(e){return I(this.getAllPOIs(e))}getYouAreHereCoordinates(e){return function(e){const t=I(e);return t?.coordinates??null}(this.getAllPOIs(e))}searchPOIs(e,t){return function(e,t){const o=t.trim().toLowerCase();return o?e.filter(e=>{const t=e.name?.toLowerCase().includes(o),i=(e.keywords||[]).some(e=>e.toLowerCase().includes(o));return t||i}):[]}(this.getAllPOIs(t),e)}async wayfindBetweenWaypoints(e,t,o){return this.wayfinding.wayfindBetweenWaypoints(e,t,o)}async navigateFromKioskToDestination(e){return this.wayfinding.navigateFromKioskToDestination(e)}clearRoute(){this.wayfinding.clearRoute()}getCameraPosition(){return F(this.map)}getMap(){return this.map}destroy(){this.map?.remove(),this.map=null,this.floorsApi.setFloors([]),this.defaultCamera=null,this.viewModes=new b(()=>this.map)}async setCurrentFloor(e){await this.data.ensureFloorGeojson(e),await this.floorsApi.setCurrentFloor(e),this.setFloorLayerVisibility(e.id),this.events.emit("floorChanged",{floor:e})}isReady(){return!!this.map}setFloorLayerVisibility(e){const t=this.map;if(!t)return;const o=this.venue?.styleSheet?.floorLayers;if(o)for(const[i,n]of Object.entries(o)){const o=String(i)===String(e);for(const e of n)t.getLayer(e.id)&&t.setLayoutProperty(e.id,"visibility",o?"visible":"none")}}getBoundsPadding(){return this.config.options?.boundsPadding??50}getVenueBounds(){const e=this.venue?.coordinates;if(!e)return null;const{bottomLng:t,bottomLat:o,topLng:i,topLat:n}=e;if(null==t||null==o||null==i||null==n)return null;const r=Math.min(t,i),s=Math.max(t,i);return[[r,Math.min(o,n)],[s,Math.max(o,n)]]}applyInitialViewFromVenue(){const e=this.map;if(!e)return;const t=this.getVenueBounds();if(t)try{e.resize(),e.fitBounds(t,{padding:this.getBoundsPadding(),animate:!1,duration:0,maxZoom:21})}catch(e){this.logger.warn("applyInitialViewFromVenue :: fitBounds failed",e)}}async loadAndPatchVenueStyle(){const e=this.venue?.styleSheet?.styleUrl,t=this.venue?.styleSheet?.floorLayers,o=j;if("sdkTemplate"===this.config.options?.styleMode)return this.logger.debug("style :: styleMode=sdkTemplate, ignoring venue styleUrl"),T({style:o,floorLayers:t,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:D});if(!e)return this.logger.warn("style :: venue.styleSheet.styleUrl missing, using baseStyle"),T({style:o,floorLayers:t,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:D});try{const o=await fetch(e);if(!o.ok)throw new Error(`HTTP ${o.status} ${o.statusText}`);return T({style:await o.json(),floorLayers:t,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:D})}catch(e){return this.logger.warn("style :: failed to fetch venue styleUrl, using baseStyle",e),T({style:o,floorLayers:t,customSprite:this.config.options?.customSprite||null,defaultSpriteUrl:D})}}ensureFloorLayersFromStyle(e){const t=this.venue?.styleSheet?.floorLayers;if(t&&Object.keys(t).length)return;const o={};for(const t of e.layers||[]){const e=t.id||"",i=/_(\d+)$/.exec(e);if(!i)continue;const n=i[1];o[n]||=[],o[n].push({id:e})}this.venue||={},this.venue.styleSheet||={},this.venue.styleSheet.floorLayers=o}ensureCoreSources(){const e=this.map;if(!e)return;const t={type:"FeatureCollection",features:[]};i.ensureGeoJson(e,n),i.ensureGeoJson(e,s),i.ensureGeoJson(e,r),e.getSource(a)||e.addSource(a,{type:"geojson",data:t,lineMetrics:!0}),e.getSource("route-endpoints")||e.addSource("route-endpoints",{type:"geojson",data:t})}}exports.MinuteMaps=L,exports.createMinuteMapsSDK=function(e){return new L(e)};
2
2
  //# sourceMappingURL=index.cjs.map