Skip to main content

Changelog

All notable, developer-facing changes to the Wemap SDK. The SDK follows semantic versioning: breaking changes only land on a major version, new features on a minor, fixes on a patch.

14.8.2​

πŸ› Fixes​

  • 14.8.1 was published with stale internal pins: @wemap/providers and @wemap/positioning required @wemap/routers@14.8.0 and @wemap/utils@14.8.0, and @wemap/geo required @wemap/utils@14.8.0, so installing 14.8.1 pulled in a second copy of @wemap/core and @wemap/geo. Every @wemap/* dependency is now pinned to the release version.
  • @wemap/geo and @wemap/positioning no longer depend on @wemap/utils, which they did not use.

14.8.1​

πŸ› Fixes​

  • Custom indoor stylesheets with extra POI marker layers (listed as symbol layers in their wemap:layers-name metadata default entry) now have those layers filtered too: a highlighted or selected pinpoint no longer also shows its default marker there, and filterPois() hides non-matching pinpoints on them (@wemap/map).
  • The viewer and viewer-map API reference pages link to the sibling packages correctly (@wemap/viewer, @wemap/viewer-map).

14.8.0​

This release adds a 360Β° panorama viewer β€” @wemap/viewer and @wemap/viewer-map β€” and lets an app that already loads its livemap host @wemap/map without fetching it twice.

✨ New features​

360Β° viewer (@wemap/viewer, @wemap/viewer-map)​

  • Look around and walk the photos captured on site. WemapViewer.open() opens a node by id or by position (the nearest photo on that level) with an initial heading and pitch, and resolves once the photo is on screen. navigateTo(), nearestNode(), getNodes() and loadGraph() (fetch the image graph without opening a photo) navigate the graph; moves between photos travel through space. Requires a livemap with a VPS provider β€” see the viewer guide.
  • Measure and locate. Click modes return the geo position under a click (locate) or the distance between two clicks (measure), from the VPS depth.
  • Overlays and interaction. World-anchored polygons (setPolygons) and labels (setLabels), lookAt(), a hover event, walkable(from, to) to limit where a click can walk to, claimClick to take a click for your own overlays, and a field of view on open().
  • On the map. ViewerGraphLayer draws the image graph (click to move there), ViewerHeadingMarker shows where the viewer looks, and ViewerMapSync keeps map and viewer on the same node and level.

Map (@wemap/map, @wemap/core)​

  • Host the map from an app that already has the livemap. core.init({ livemap, env }) parses an already-fetched livemap (GET /livemaps/{emmid}) with no request.
  • preloadPinpoints: false turns off the viewport pinpoint preload, for apps that load pinpoints themselves.
  • Camera eventData. setCenter, setZoom, flyTo, easeTo, fitBounds and the new jumpTo take an optional last eventData argument, merged into the move* / zoom* events β€” to tell your own camera moves from user gestures.
  • bounds: null / maxBounds: null ignore the snippet's bounds (no initial fit / an unconstrained camera); omitting them still uses the snippet's.
  • Default attribution now credits Wemap, MapLibre and OpenStreetMap. Pass attributionControl: false to hide it.

Positioning (@wemap/positioning)​

  • Wall crossing. VPSLocationSource can degrade the location state when the walk crosses a wall, until the next successful scan. Configure it with the wallCrossing option (enabled, walls per level, locationImpact: degraded or no_positioning) or from the livemap snippet (arnavigationdata.wallCrossing). Off unless enabled; without walls, the walls of the venue are fetched once.
  • Snippet-driven tuning. Map matching reads its parameters from the snippet (arnavigationdata.<indoor|outdoor>.mapmatching), and the VPS degraded / lost walking distances from arnavigationdata.providers. Code options still win.

Routing (@wemap/routing)​

  • Caller identity. directions() sends the app identity given to core.init({ client }), so route usage is attributed to your application.

⚠️ Behavior changes​

  • Orientation matching is off by default (@wemap/positioning). A livemap that enables it in its snippet still gets it.
  • Default attribution is shown on WemapMap (it was hidden). See above.
  • VPS requests are bounded (@wemap/positioning, @wemap/providers): a scan gives up after maxScanDuration (2 min by default), background scanning stops after maxDurationMs (30 min by default, reported as 'expired'; a user-initiated scan re-arms it), and each /geopose request times out after 20 s.
  • InitOptions (core.init) is now a union: { emmid, token } or { livemap }. Calls compile as before; only code reading emmid / token off an InitOptions-typed value needs a narrowing check.

πŸ› Fixes​

  • Positioning keeps running after a VPS scan times out; it used to stop PDR too (@wemap/positioning, @wemap/providers).
  • VPS no longer multiplies its request loop on restarts or uploads black frames (@wemap/providers, @wemap/camera).
  • Level.contains works with a reversed range (@wemap/geo).
  • Routing: stacked stairs stay on their own floors in a GeoJSON graph, and two flights ending on the floor they share are still joined (@wemap/routers, also in 14.7.7).

14.7.1 – 14.7.7​

Routing patches (@wemap/routers, @wemap/osm):

  • A routing request can bring its own rules, so a venue graph shared by several livemaps routes with each livemap's rules (14.7.1).
  • The OSM import reports elevators whose levels are not connected (14.7.2).
  • osmStringToGraphGeojson returns the graph in the shape Wemap Pro edits: elevator areas as points, backward one-ways redrawn forward, one object per way (14.7.3, 14.7.5). OSM XML is parsed with the browser's DOMParser when there is one; elevator points and polygons are selected by geometry type; polygon elevator levels stay apart (14.7.3).
  • An itinerary leaving a custom map takes the exit with the fastest remote route; enter / exit is announced only where the level changes across the door (14.7.4).
  • conveying=no means no conveyor and oneway=-1 one-way backward (14.7.5); every entrance value but no imports as an entrance (14.7.6).
  • Stacked stairs stay on their own floors, and flights ending on a shared floor are joined (14.7.7).

14.7.0​

✨ New features​

  • Waypoints in directions. Router.directions() accepts intermediate waypoints between origin and destination, plus optimizeWaypoints to reorder them for the shortest route (@wemap/routing).
  • No-build <script> integration. Every package now ships a UMD bundle you can drop in with a <script> tag β€” no bundler required. Globals live under the Wemap namespace. The @wemap/map bundle is self-contained (maplibre-gl and its worker are inlined).

πŸ› Fixes​

  • Turn-by-turn steps no longer overwrite the street name with the motorway exit number (@wemap/routing).

14.6.1​

πŸ› Fixes​

  • Coordinates now uses the WGS84 ellipsoid instead of a sphere (@wemap/geo, @wemap/map). Distances, ECEF conversions, local frames and the accuracy ring are more accurate; returned values change.
  • GeoRef.heading now rotates around the local vertical, in radians clockwise from north.

14.6.0​

This release introduces @wemap/map β€” a new, dedicated package for rendering Wemap livemaps on top of maplibre-gl β€” alongside a modular package layout (@wemap/core, @wemap/geo, @wemap/map, @wemap/positioning, @wemap/routing, @wemap/camera). You now install only the packages you need.

✨ New features​

Map rendering (@wemap/map)​

  • Livemap-aware map wrapper. Construct a WemapMap after core.init() and your livemap's style, bounds, zoom range, pitch, bearing and indoor settings apply automatically. Override any of them β€” plus all maplibre options β€” in the constructor. The raw maplibre instance stays available as map.maplibre as an escape hatch.
  • Camera and events. First-class helpers for setCenter, setZoom, flyTo, easeTo, fitBounds, and typed on / once / off event subscription.
  • LatLngLike inputs everywhere. Position inputs accept a Coordinates, a { lat, lng, level? } object, or a [lat, lng, level?] tuple β€” all latitude-first. Malformed positions are validated and rejected early.
  • whenReady() and autoResize. Await a race-free "map is ready" signal, and let the map resize itself with the container automatically.
  • POIs & content search. Click, highlight, select and filter livemap pinpoints; run content search; and read viewport pinpoints with a loading signal to know when results settle.
  • Markers & clustering (DomMarkerLayer). Add runtime markers with a custom element, icon, color, anchor and offset; update them in batches with setMarkers; and opt into supercluster clustering.
  • Shapes (ShapeLayer). Draw GeoJSON lines and polygons with simplestyle-spec styling, plus hover and click.
  • Itineraries (ItineraryLayer). Render multilevel routes on the map.
  • User location (UserLocationLayer). Show the user from a positioning stream, including a geographic accuracy ring.
  • Indoor & levels. Automatic building selection, pose-driven level sync, a LevelControl floor switcher, and level-aware custom layers.
  • Theming. Brand the map through design tokens set at core.init({ theme }) and a public set of CSS variables and classes for finer control.

Geocoding (@wemap/core)​

  • Forward and reverse geocoding via a new GeocodingService β€” turn an address into coordinates and back.

Routing (@wemap/routing)​

  • itineraryRules options for finer control over computed routes.
  • Strict map-matching (useStrict) to snap tightly to an itinerary, and orientation-aware matching.

Positioning (@wemap/positioning)​

  • Location state reporting and a more resilient background VPS scan.

πŸ› Fixes​

  • Multilevel itineraries no longer bleed across floors.
  • Indoor level filtering now applies correctly while GeoJSON sources are still loading.
  • More reliable indoor routing across mixed-level graphs, with more accurate turn directions at route-leg junctions and corrected wheelchair handling for elevators and moving walkways.
  • Faster indoor graph routing.

For full API details, see the package API reference and the feature guides.