Skip to content

Changelog ​

3.39.1 (2026-09-24) ​

🩹 Fixes ​

  • Smoother interaction on large floor plans: selecting a booth, opening and closing Directions, and opening the Directions booth dropdown no longer freeze the map, and booth dots appear as soon as you zoom out.

3.39.0 (2026-09-24) ​

🚀 Features ​

  • A layer can now be drawn above 3D content with LayerDef.overlay, so wayfinding routes and their markers stay visible over booth volumes. Image and text defs can set screenSpace to face the viewer while keeping their plan anchor and their size in plan units, which is what a map pin needs. Both are opt-in, and a scene that sets neither renders exactly as before. Wayfinding now uses both on a 3D plan, so the route and its icons stay visible over booth volumes and the icons stand up to face the viewer.

3.38.0 (2026-09-24) ​

🚀 Features ​

  • Floor plans with many booth logos now load without freezing. Image pixels are prepared off the main thread, so panning and zooming stay responsive while a plan's logos arrive.

    Exhibitor logos supplied as SVG are drawn again.

    Exhibitor data can now carry logoAspectRatio, the logo's width divided by its height. When an event supplies it, the floor plan fits that logo into its booth without decoding the image to measure it.

    Image sources passed to the renderer must now be a Blob, a canvas, an ImageBitmap or an OffscreenCanvas. An HTMLImageElement is no longer accepted — fetch the image and pass its Blob instead.

3.37.1 (2026-09-24) ​

🩹 Fixes ​

  • Fit to screen and other camera moves now animate smoothly when they start after the plan has been idle, instead of sometimes jumping straight to the end.

3.37.0 (2026-09-24) ​

🚀 Features ​

  • Fixes the setkiosk panel's Save button staying disabled after the map was re-framed: for a kiosk that already exists, panning, zooming, rotating or tilting the view — by hand or with the map controls — now counts as an unsaved change, on the floor plan and on the map alike, and closing the panel warns before those changes are dropped. Opening the panel still reports no changes until the operator makes one. Moving the plan also keeps the kiosk's idle timer alive again, so the home view stops returning while a visitor is still exploring.

    Three more kiosk-mode fixes around the same panel: the idle timer that returns the home view no longer runs while the panel is open, so an operator can take their time over a placement; typing kiosk=0 — or opening the plan with ?kiosk=0 — while the panel is open now turns kiosk mode off for good, where it used to be reverted the moment the panel closed; and a device that cannot write to local storage, a browser in private mode or one with site data blocked, can leave kiosk mode again instead of being stuck in it until the page is reloaded.

    In @expofp/renderer, the camera hook useCameraMoveStart is replaced by two: useCameraMoveEnd, which reports any movement once it has come to rest, and useCameraGesture, which reports the user's own hand on the camera.

🩹 Fixes ​

  • Internal: fix test timeouts when the whole workspace's tests run in parallel. No SDK-facing or runtime changes.
  • Fix a deleted kiosk keeping the device in kiosk mode: deleting the kiosk now takes kiosk mode with it, after a reload as well as when the setkiosk panel closes. A kiosk position set in the event config still applies and is no longer switched off by the delete. Closing the panel no longer leaves kiosk mode on by itself, stops an idle reset that was already due, and drops a UI scale that was only tried out.

3.36.0 (2026-09-22) ​

🚀 Features ​

  • Images placed by the designer no longer turn as the plan is rotated: they stay exactly as drawn, so an arrow or a sign keeps pointing where the designer pointed it. Exhibitor logos in booths still follow the plan, so they stay readable at any angle, and bookmarks, markers and route icons are unchanged. A temporary measure until the designer can mark an image as rotatable.

3.35.2 (2026-09-22) ​

🩹 Fixes ​

  • Fixes the kiosk "View Map on Phone" QR code and the ExpoFP logo being painted underneath the floor plan: both are now drawn on top of the map, as the rest of the on-screen controls are.

3.35.1 (2026-09-21) ​

🩹 Fixes ​

  • Fixes a re-layout stall: when the renderer's per-frame layout budget was already spent as the pass began, that pass could lay out nothing at all and retry the same way on the next frame. Labels, badges and markers that resize with the zoom now always make progress, so they settle instead of occasionally lagging a frame behind on a busy device. Also an internal refactor of the renderer with no effect on behavior or public API.
  • Event pages are now search-engine ready: the browser tab shows the event name as soon as the event data loads, and the page gets a meta description, a canonical URL and a page heading built from the event's name, venue and dates. Pages of removed or unknown events are kept out of search results. Maps served under locomaven.com say "by LocoMaven" instead of the wrong vendor name. When the SDK is embedded on a third-party page, the host page's title and head are left untouched.
  • Fixes the sidebar list occasionally opening empty: the search results (and any list inside the panel) could stay blank after a click on the search field until something else redrew the panel. The panel now hands its scroll container to the list in the same frame it appears, and the bottom sheet's slide-up no longer depends on a timer racing the panel's mount.

3.35.0 (2026-09-17) ​

🚀 Features ​

  • A new 3D look for the plan, and the settings that drive it.

    The light rig holds one fixed pitch on the camera's heading and derives both light intensities from a single contrast value. A roof lands on the color it was authored with, and no surface blows out. Two darkening effects give the plan its depth. A contact shadow darkens toward the base of every volume, which separates a floor, a wall side and a wall top. Ambient occlusion darkens where two surfaces crowd each other, such as an inside corner or a booth standing beside a model. The contact shadow runs on every device the SDK reaches. Ambient occlusion switches itself off on a device that cannot give it what it needs, and the contact shadow stays.

    RendererProps.lighting sets these values. It takes the rig's contrast and its three light colors, plus a shadow object holding the shade both effects blend toward and each effect's own reach and strength. Every field is optional, and an omitted field keeps the design's own default.

    The plan can also open at an angle. pitchdegrees, pitchtime and the pitch gesture flag join the map settings beside the roll and zoom ones. CameraSchema gains pitchDegrees and pitchTime. Both views a plan is drawn in read the same settings, so the floor plan view and the MapLibre map open at the same angle and ease over the same time.

    hide3dMapDefault no longer selects the view the map opens in. A venue that sets allow3dView now opens its map tilted, and can tilt it by hand, whatever hide3dMapDefault says. Nothing in the SDK reads that flag any more.

🩹 Fixes ​

  • Kiosk mode no longer switches on when the floor plan is opened on a phone-sized screen. Scanning a kiosk's route QR code now shows the route in the mobile layout, framed to fit the phone, instead of the kiosk layout that left it zoomed far out.

3.34.2 (2026-09-17) ​

🩹 Fixes ​

  • Point-of-interest icons now stand out on the map when a highlight picks them out — a category search button, a poiTypes filter, a search hit, or the highlightBooths API. They take the plan's accent color instead of staying the gray they are authored in, which the dimmed plan rendered as the same gray.

3.34.1 (2026-09-17) ​

🩹 Fixes ​

  • Telemetry now delivers a backed-up event queue in several requests instead of one oversized POST, and drops a batch the endpoint refuses outright rather than retrying it forever. Previously a backlog too large for the endpoint stopped all telemetry for that visitor until they cleared their browser storage.

3.34.0 (2026-09-16) ​

🚀 Features ​

  • @expofp/wayfinding owns the layers it draws into: initWayfindingLayers() builds the block the host mounts, resolveWayfindingLayers() finds it in the scene again, and nothing outside the package names a layer — IconConfig.layer becomes onTop, and setTrail/setRouteLines drop their layer arguments along with LayerNames. RendererPort keeps only what a host can answer for: attachCardinalSnap and update. Tearing an instance down empties the layers it was given, instead of leaving the last route drawn over the plan.

3.33.0 (2026-09-16) ​

🚀 Features ​

  • The debug panel now reports the plan coordinates under the pointer, with the floor they are on, so a coordinate can be read straight off the plan instead of being clicked for. Debug builds only.

    @expofp/renderer publishes useDebugPanel, the hook a host uses to put its own values into that panel.

3.32.0 (2026-09-16) ​

🚀 Features ​

  • @expofp/wayfinding consumers: RendererPort drops getRotation, and its createImageDef gains a cardinalSnap option — the host now attaches the rule that keeps an icon readable as the camera rolls. Wayfinding.applyRoll and Wayfinding.applyScale go with it: icons and trails follow the camera through the handlers their own defs and layers declare, which the renderer dispatches.

    A wayfinding trail no longer flashes when a zoom settles: the dots it already holds are moved to their new spacing rather than rebuilt, so they follow the camera in the frame it moves.

    Cardinal-snap icons keep the heading they hold when a route, position or floor change repositions them, instead of dropping flat until the camera next turned. Icons, booth labels, badges and bookmarks also catch up with a camera that jumped more than a quarter — a restored kiosk or setCamera — rather than stopping a quarter short.

3.31.5 (2026-09-14) ​

🩹 Fixes ​

  • The loading spinner now stays until the plan's layers are ready, instead of leaving the container empty while the plan is still being built.

3.31.4 (2026-09-09) ​

🩹 Fixes ​

  • No change to the published API. Internal only: each React component now sits in a module Fast Refresh can swap in place, so a dev-server edit no longer reloads the page.

3.31.3 (2026-09-08) ​

🩹 Fixes ​

  • Fix the setkiosk panel rendering unstyled: its stylesheet reaches the floor plan again when Shadow DOM is on.

3.31.2 (2026-09-08) ​

🩹 Fixes ​

  • Selecting a booth or exhibitor from the plan's ready callback now zooms to it, as it does at any later moment. Camera commands issued in the moment the plan comes up are no longer dropped.

3.31.1 (2026-09-04) ​

🩹 Fixes ​

  • Bus/transport traffic: plans without the busRoutes flag no longer open a WebSocket to routes-api on network reconnects, and the socket is closed when the plan is torn down instead of reconnecting forever.

3.31.0 (2026-09-04) ​

🚀 Features ​

  • Mobile bottom-sheet fixes for #1567: the sheet gets vaul-style drag physics with three snap points, lifts above the on-screen keyboard, the route-planner autocomplete dropdown flips upward when there is no room below, and the planner form opens at medium instead of a blank full-height sheet.

🩹 Fixes ​

  • Steady the mobile bottom sheet while the on-screen keyboard opens, and expose the active screen id on the search box (data-interface) so custom CSS can target one header.
  • Render the route planner's option list inside the mobile bottom sheet instead of a positioned dropdown, which the on-screen keyboard pushed out of view.

3.30.0 (2026-09-04) ​

🚀 Features ​

  • Normalized expo form in the cloud: the next contour's generator now writes every expo folder in the normalized form by default — the manifest snapshot and every resource live in the expo's content-addressed immutable/ store at fixed https://<expo>.expofp.com/immutable/… URLs, deduplicated across revisions and served with a forever cache. @expofp/config exposes serializationFormat() — the identity of the snapshot form a generator stamps its artifacts with, so a runtime never serves a snapshot of another format.

3.29.0 (2026-09-04) ​

🚀 Features ​

  • Normalized expo form: loadConfig follows the mutable manifest.json pointer to its immutable snapshot and expands $/<expo>/<hash>/<name> store refs — in manifest fields, document $refs, drawing hrefs and CSS urls — into their canonical https://<expo>.expofp.com/immutable/… URLs, so effective configs are unchanged for consumers; the codec ships as resolveUrl / compactUrl. Offline copies and compat manifests load exactly as before.

3.28.3 (2026-09-02) ​

🩹 Fixes ​

  • Dev harness: the Vite dev server accepts ?expo=<name> to override VITE_EXPO, so one server can switch venues without a restart.
  • 3D models placed on a floor plan now load wherever the plan is served from: a model file is resolved against the plan's data directory like every other drawing asset. Models also survive an offline copy — the model files are bundled with the plan instead of being left behind.

3.28.2 (2026-09-02) ​

🩹 Fixes ​

  • Booths in the MapLibre map view are shaded correctly again. Solid 3D booths were rendering flat black there: the plan was placed in the map's own coordinate space, which reads its vertical axis the opposite way round, so every lit surface was lit from behind. Booths now shade from their own colors, with walls turning away from the camera darkening as they do on the standalone plan.

3.28.1 (2026-09-02) ​

🩹 Fixes ​

  • Internal cleanup of stale design-note references in code comments; no functional changes.

3.28.0 (2026-09-02) ​

🚀 Features ​

  • The MapLibre map now credits ExpoFP with a link in its attribution panel.

3.27.1 (2026-08-31) ​

🩹 Fixes ​

  • Pinch-to-zoom with two fingers on a Mac trackpad now zooms the floor plan. The gesture previously did nothing at all: it was swallowed before it reached the camera, so neither the plan nor the page zoomed. Two-finger scroll, mouse wheel and touch-screen pinch are unchanged.

3.27.0 (2026-08-31) ​

🚀 Features ​

  • The floor plan draws through the new React renderer everywhere, the MapLibre embed included: labels and badges hold their on-screen size and stay upright while the map zooms and turns, wayfinding, markers and live traffic work in map mode, and clicking booths behaves the same on the plan and on the map. Debug tooling now works in the embed too.

3.26.0 (2026-08-31) ​

🚀 Features ​

  • Report additional viewer interactions to analytics: session views, speaker views, bookmark clicks, and clicks on the search buttons above the plan — including the session sub-buttons and the list filter chips, which are tagged so they stay separable from the main row

🩹 Fixes ​

  • Stats for a floor plan loaded after unstable_destroy() are reported under that plan's event instead of staying tagged with the previous one — the event key, its id and the referrer trail all reset with the plan
  • Stats: events are no longer credited to the wrong floor plan when one plan is destroyed and another is loaded in the same page, the first "All Tracks" click and re-clicks of a booth whose card is already open are counted, and a link button no longer counts clicks that open nothing. Fixes a point-of-interest filter switching back on when tapped to clear it
  • Stats: a bookmark click on a session or speaker is no longer also counted as a share, and clicking a booth whose exhibitor card is already open — including a second booth of the same exhibitor — is counted instead of being dropped
  • Telemetry batches now carry the expo key as an ?expo= query parameter on the request URL alongside the existing payload field.
  • Stats no longer mislabel an exhibitor view as a view of a previously clicked booth — reopening a single-exhibitor booth no longer costs the next exhibitor view

3.25.2 (2026-08-31) ​

🩹 Fixes ​

  • Map view: getCenterCoordinates() now reports the plan coordinates at the centre of the map instead of failing. It previously only worked in the floor plan view; in map view the call recursed until the call stack overflowed.

3.25.1 (2026-08-27) ​

🩹 Fixes ​

  • Booth and area labels no longer vanish when a plan publishes a booth border width far larger than the strokes it draws. The label inset is now clamped for every label drawer, matches the border that is actually painted, and no longer breaks on an unparsable or negative stroke width.

3.25.0 (2026-08-27) ​

🚀 Features ​

  • Floor plans can now be torn down with destroy(), so a single-page app can leave and re-enter a map route cleanly. The container element is released for reuse, and calling it while the plan is still loading cancels the load instead of failing — the ready promise then rejects rather than waiting forever, so catch it if you await it. The unstable_destroy() alias keeps working but is deprecated.

3.24.3 (2026-08-26) ​

🩹 Fixes ​

  • Offline PMTiles basemaps now render on hosts that do not support HTTP range requests, such as the Android SDK's WebView asset loader.

3.24.2 (2026-08-26) ​

🩹 Fixes ​

  • Map view: the re-centre button zooms in on the blue dot instead of only centring on it, matching the floor plan view

3.24.1 (2026-08-26) ​

🩹 Fixes ​

  • Map view: the blue dot, routes and markers now appear as soon as they are set, instead of waiting for the user to pan the map on large plans

3.24.0 (2026-08-24) ​

🚀 Features ​

  • The direction callback now states what it has always sent. onDirection is called with null when the route is cleared, and a route being built reports from or to as null until both ends are picked, so both are typed that way. An endpoint picked on the map — the blue dot, a kiosk anchor — carries the layer name it snapped to and no external id, which the new FloorPlanDirectionEndpoint type spells out. TypeScript embedders reading e.from.name will be asked to handle the empty case; the values arriving at runtime are unchanged.

    Two fixes came out of the same pass. A floor selector no longer greys out every floor when a route runs on layer names the plan does not carry — only the floors the route really leaves out are disabled. And getBooth with a GPS position the plan cannot place — invalid coordinates, or a fix far outside the venue — now answers with nothing instead of pointing at an arbitrary booth.

3.23.4 (2026-08-24) ​

🩹 Fixes ​

  • A floor plan re-created on the same page now draws again: the store is re-pointed at the new container instead of the previous, detached one.

3.23.3 (2026-08-24) ​

🩹 Fixes ​

  • Re-creating a floor plan on the same page now renders styled: chunk styles are re-adopted by the new instance instead of being stranded in the discarded one.

3.23.2 (2026-08-23) ​

🩹 Fixes ​

  • Blue dot: re-centre now switches to the dot's floor under MapLibre too; the first-fix focus works under MapLibre and no longer drops a fix that arrives before the renderer is ready

3.23.1 (2026-08-20) ​

🩹 Fixes ​

  • Internal: extract Gallery and Overlay into @expofp/ui as pure presentational components, move overlay sizing math into a dedicated OverlayStore, and drop the unused Toast component. No SDK-facing or runtime changes.

3.23.0 (2026-08-18) ​

🚀 Features ​

  • Deep links from the mobile SDKs no longer leak into the search box: ?agenda now opens the sessions panel (deprecated — use ?showList=sessions), and the dead ?sw=, ?yah= and ?k= parameters are ignored instead of being replayed as search text.

🩹 Fixes ​

  • Retired the legacy URL parameters whose capability the schema-typed form now covers: ?center=, ?centerxy=, ?z=, ?bearing=, ?zoomtime= (use ?camera[lat]/?camera[lng], ?camera[x]/?camera[y], ?camera[floor], ?camera[bearing], ?camera[zoomTime]), ?hide= (use ?visibility[…]=false) and ?lang= (use ?changeLanguage=). Also retired: the ?kkiosk/?nokkiosk search commands — use ?kiosk=1/?kiosk=0 instead, which also work typed into the search field on kiosk devices; ?b=/?ba=, the legacy bookmark-import links and the bookmark-list share button that produced them, so old links now open a clean plan — and, unlike before, a ?blue-dot= or ?viewermode= sharing the query still applies instead of being swallowed with the import; ?roll=, which locked one link against map rotation and has no per-link replacement — turn rotation off for the whole plan with enableRotation in the event data instead; ?pathway= with its ?booths= companion — use the ?showPathway[0]=p-1&showPathway[1][0]=… shortcut, or ?selectTour=t-1 when the old link also carried a tour= id, since a tour draws its pathway and opens its header together; ?build-route — use ?startBuildRoute; the dead ?-pdf; and the ?preview=/?copy_exh= development parameters. A link still carrying a retired parameter opens the floor plan normally — the parameter is ignored instead of turning into search text.

    Two migration notes: ?visibility[…] rebuilds the whole map chrome, so a link must list every element it wants hidden rather than translating ?hide=/?noOverlay= key for key; and ?changeLanguage= reports an unknown language as an SDK error where ?lang= silently ignored it.

    ?noOverlay= and ?allowConsent= are deprecated rather than removed: they keep working — at boot and through applyParameters() alike — while you migrate to ?visibility[overlay]=false and ?consent=granted|denied, and the canonical key wins when a link carries both. The reference documents these two under "Deprecated parameters"; it no longer lists the retired ones at all — it describes only parameters that still do something, so these release notes are where a retired parameter's replacement is written down.

    The legacy kiosk_* URL channel is now just the anchor position — kiosk_x, kiosk_y, kiosk_z, the keys a kiosk's route QR code actually emits so the scanning phone can resolve where the route starts. The other eleven (kiosk_heading, kiosk_lat, kiosk_lng, kiosk_iconSizePercent, kiosk_uiScale, kiosk_mapRollDegrees, kiosk_mapInitialPtScale, kiosk_mapPtScale, kiosk_mapCenterX, kiosk_mapCenterY, kiosk_mapPitch) are retired; set a kiosk anchor through the schema-typed ?kiosk[…] form, the manifest or the embed options instead.

    Multi-exhibitor selection URLs (?exhibitors=) now carry exhibitor display names instead of encoded exhibitor IDs. ?exhibitors=true keeps its older meaning — open the exhibitors list — instead of also searching for an exhibitor named "true".

    Fixed along the way: ?layer= and the route QR code's ?kiosk_x/y/z no longer leak into the selection. A link carrying ?layer= still opened the search panel with its own query typed into it, and a kiosk_x/y/z tail rode into whatever it shared the link with — corrupting a booth name, and silently turning an accessible route into a normal one, which is the scanned-QR link these keys exist for. Also: a floor plan whose drawing holds booth shapes with no rectangle could keep some of them — unplaced and unusable — instead of dropping them all.

  • Fit-to-screen and the initial view now frame the authored viewbox identically with and without the MapLibre basemap. On a plan rotated relative to north the map fit previously zoomed out well past the venue, and Fit-to-screen framed the venue more loosely than page load did.

3.22.0 (2026-08-13) ​

🚀 Features ​

  • Internal settings for mobile SDKs: fp.getInternalSettings() returns the allowlisted event settings (mobileLocationProvider), plus the new nullable mobileLocationProvider config field.

3.21.1 (2026-08-12) ​

🩹 Fixes ​

  • Publish @expofp/ui — the standalone package of the SDK's shared pure, presentational React UI components — on npm again.

3.21.0 (2026-08-12) ​

🚀 Features ​

  • Add @expofp/ui, a standalone package of the SDK's shared pure, presentational React UI components (extracted from @expofp/floorplan).

🩹 Fixes ​

  • Internal: reorganize the @expofp/ui source tree so every component lives under src/components/. No SDK-facing or runtime changes.
  • Stop publishing the internal @expofp/ui package; its components are already bundled into the floorplan build.
  • Custom event fonts now apply to booth labels on the map view, not just the floorplan view.

3.20.1 (2026-08-11) ​

🩹 Fixes ​

  • A map center of 0,0 is no longer ignored, and a malformed one is no longer applied: centerxy and center now have to parse as two finite numbers before the map pans to them.

3.20.0 (2026-08-10) ​

🚀 Features ​

  • The runtime now honors the manifest's legacyDataVersion pin: legacy data files are cache-busted with the pinned revision and the client-side version.json probe is skipped (one fewer request; manifest and data stay consistent). A manifest can also state "no version exists" (legacyDataVersion: null) — the runtime then cache-busts per load with a fresh timestamp, still without probing. Only manifests that predate the pin (the field absent, or the retired $ref-shaped pointer) fall back to the probe exactly as before, and the designer preview keeps its fresh-timestamp cache-busting. The ?expo= page-URL parameter is now recognized as the delivery platform's routing param: it never opens a search, never merges into the config, and survives the floor plan's URL rewrites, so preview URLs /s/<sha>/?expo=… stay reloadable and shareable.

3.19.0 (2026-08-09) ​

🚀 Features ​

  • Add experimental outdoor POI markers to the MapLibre map: booths on an Outdoor designer layer render as fixed-size native markers with clustering, instead of as plan shapes. Off by default — set enableExperimentalOutdoorMarkers to turn it on. While it is off, Outdoor layers render exactly as before.

3.18.1 (2026-08-05) ​

🩹 Fixes ​

  • Booth number badges (shown over exhibitor logos when the label is hidden) now reposition to the correct corner and stay upright as the map is rotated.

3.18.0 (2026-08-04) ​

🚀 Features ​

  • Kiosk mode on the MapLibre map now returns to its saved home view after the idle timeout, and panning or zooming the map keeps the kiosk awake.

3.17.0 (2026-08-04) ​

🚀 Features ​

  • The MapLibre map view is now available on kiosk displays. Kiosks running a map-enabled plan open in map mode like any other device, instead of always falling back to the flat floor plan.

3.16.2 (2026-08-03) ​

🩹 Fixes ​

  • Fix a rare horizontal scrollbar appearing at the bottom of the exhibitor/booth details panel

3.16.1 (2026-08-03) ​

🩹 Fixes ​

  • Offline floor plan copies now ship a basemap that matches the online light theme.

3.16.0 (2026-08-03) ​

🚀 Features ​

  • Plans authored for the map in the Designer now open on the MapLibre basemap automatically — no flag needed. Setting enableExperimentalMaplibre to false still keeps such a plan on the plain floor plan.

3.15.0 (2026-07-30) ​

🚀 Features ​

  • New searchButtons element in the visibility node: keep the search-filter buttons visible while the overlay panel is hidden — clicking a button opens the overlay on demand and closing it returns to the buttons-only view. Enable it with ?noOverlay=true&visibility[searchButtons]=true (or the canonical ?visibility[overlay]=false&visibility[searchButtons]=true), from the manifest's visibility node, or at runtime via FloorPlan.setVisibility({ overlay: false, searchButtons: true }). Omitted, searchButtons keeps following overlay, so existing noOverlay/?hide=overlay links behave exactly as before.

3.14.0 (2026-07-30) ​

🚀 Features ​

  • Add a dark basemap to the map view. The palette follows the drawing: a plan authored for a dark surround gets the dark basemap, one authored light gets the light one. Plans that do not declare a palette fall back to their background color. A custom maplibre.style / maplibre.styleUrl is unaffected.

🩹 Fixes ​

  • Fix the free-plan promo banner overlapping the exhibitor logo strip instead of sitting below it
  • Fixed the route planner's starting point search sometimes showing the same location duplicated (or missing) when a booth had more than one exhibitor listing.

3.13.4 (2026-07-28) ​

🩹 Fixes ​

  • Fixed an intermittent issue where the search panel could fail to open after tapping the search icon in Safari.

3.13.3 (2026-07-28) ​

🩹 Fixes ​

  • URL map settings (?bearing=, ?zoomtime=, ?center=, ?centerxy=, ?z=, ?roll= and the ?camera[…]= form) officially apply only to the load that carries them: the in-tab session persistence — a parameter-less reload re-applying settings from earlier in the browser-tab session — is removed from the code and the docs. In practice nothing changes at runtime: that persistence had been broken since a December 2025 regression and never saved anything. Kiosk devices are unaffected — the kiosk stores and restores its own position and camera itself. FloorPlan.setCamera() likewise no longer persists the camera into the tab session.
  • The ?zoom= query parameter is removed from the documentation and the SDK types. It has had no effect since the map renderer was replaced — the value was parsed and discarded, never applied to the camera. Nothing changes at runtime: use the map controls, or ?camera[bearing]=/?camera[x]=/?camera[y]= and FloorPlan.setCamera() to frame the plan on load. ?zoomtime= is unaffected and keeps working.

3.13.2 (2026-07-27) ​

🩹 Fixes ​

  • Fix the ESM build throwing [mobx] The provided value could not be converted into an observable on import. It affected bundlers that resolve the import export condition instead of browser — SSR and node-target builds — where it made the floor plan's stores unusable. Browser builds were never affected.

    Update the SDK build toolchain and dependencies. No changes to the public API.

3.13.1 (2026-07-23) ​

🩹 Fixes ​

  • Avoid unnecessary floor changes for same-floor wayfinding routes while preserving intentional cross-floor virtual transitions.

3.13.0 (2026-07-22) ​

🚀 Features ​

  • The onDirection event now returns route lines in walking order (source→destination); earlier releases returned them reversed (target→source, with p0/p1 swapped).

    Fix a route-line segment disappearing at a floor transition while a live position is active.

3.12.3 (2026-07-21) ​

🩹 Fixes ​

  • Heatmap colors now apply to complex booths and booth borders, and render in grayscale when monochrome mode is enabled

3.12.2 (2026-07-21) ​

🩹 Fixes ​

  • Internal: error reports now tag their source as main.

3.12.1 (2026-07-17) ​

🩹 Fixes ​

  • Booth labels and bookmarks now stay upright and readable when the floor plan is rotated.

3.12.0 (2026-07-15) ​

🚀 Features ​

  • Event data now loads through a single typed config: the legacy data.json document is merged into the effective config with every asset URL (logos, galleries, speaker photos, drawing images) resolved up front, the drawing (fp.svg.js), per-layer files and the wayfinding graph load through config-managed refs, and rebooking state is merged during config load. Live events start faster — the drawing and wayfinding graph download in parallel with the event data. Offline copies store all legacy data as resolved JSON documents (no scripts), address them with relative refs so a copy serves correctly from any directory, and inline the merged event data in the copy's manifest. Offline generation is strict: a build fails instead of silently shipping an incomplete copy (the wayfinding graph and pre-scaled logo variants remain optional), and custom CSS fonts are bundled too.

    The config gains an intents field — imperative actions (selectBooth, selectExhibitor, changeLanguage) that run automatically once the floor plan is ready. Intents can also arrive via the page URL query (?intents[0][name]=selectBooth&intents[0][args][0]=A1), enabling deep links into a selected booth, exhibitor, or language.

    The new consent setting replaces the tri-state allowConsent boolean: 'granted' / 'denied' apply a pre-made cookie-consent decision, while 'ask' (the default) leaves it to the visitor — GDPR visitors get the consent prompt again and analytics are no longer disabled by default. Set it from load() options, event data, or the ?consent= URL parameter; allowConsent stays accepted everywhere as a deprecated alias, and ignoreQuery now isolates the consent decision from the page URL. Invalid URL settings no longer break loading — they are ignored.

  • New FloorPlan.setCamera({x,y,lat,lng,floor,bearing,zoomTime}) and getCamera() methods to control and read the camera; setCamera is also available as an intent from the URL.

  • URL deep links and the FloorPlan API now share one foundation. Every intent gains a typable URL shortcut (?select=biogreen-ag, ?showList=bookmarks, ?selectTour=t-1, ?startBuildRoute), alongside the existing ?selectBooth= and ?changeLanguage= forms. New FloorPlan methods: select() resolves any slug or external id the way deep links do, plus showList(), selectTour(), openPlanner() and startBuildRoute(). Presentation toggles (noOverlay, monochrome, hideHeaderLogo, hideLogoInBooth, disableFeatured, disableBookmarked, disableGps) are regular config fields now, settable from the manifest and options as well as the URL. All legacy URL forms keep working; the browser back button no longer collects duplicate history entries from URL rewrites.

  • Floor plan URLs now accept intent shortcuts — the intent name as a query key (?selectBooth=A-12, ?changeLanguage=fr), alongside the canonical bracketed intents[…] form. Shortcuts play after bracketed intents, in query-param order; an invalid value is ignored rather than breaking the load.

  • Schema validation of expo event data is now an opt-in diagnostic: enable it with ?validateSchema=1 in the URL or efp-validateSchema in localStorage to validate the manifest and referenced documents during load. It is off by default, removing the validation cost from every floor plan load.

  • New config.kiosk node — the kiosk anchor (position, floor, camera framing, per-device UI scale) is settable from the manifest, embed options or the ?kiosk[x]=… URL form; a kiosk saved on the device and the legacy kiosk_* params keep working unchanged. The undocumented dead parameters (sw, zoom, yah, agenda, k, forceKioskShowDetails) left the reference.

  • New intents selectRoute (plus the accessible variant selectAccessibleRoute), showPathway and selectCurrentPosition — build routes, highlight pathways and place the visitor position straight from a link, the manifest or the embed options.

  • New config.visibility node with the ?visibility[header]=false URL form and a setVisibility intent — control the map chrome (controls, levels, header, overlay) from any config layer; the legacy ?hide= link keeps working as an alias.

  • The initial camera is now a config node: set it from the manifest, the options object, or the URL as ?camera[x]=…&camera[y]=…&camera[bearing]=180 — the same schema-typed shape as FloorPlan.setCamera(). The legacy center/centerxy/z/bearing/zoomtime URL params keep working as aliases, and a deep link can now combine an entity slug with camera params in one URL.

🩹 Fixes ​

  • Offline copies now load per-layer drawing images correctly. A layer drawing's <image> assets (the svg-images/*.webp files) were addressed with a doubled path and failed with a 404; every referenced-document asset now resolves against the page, wherever the copy is mounted.
  • Boolean and numeric intent arguments in the URL are now coerced to their schema types: ?openPlanner[fromBookmarks]=true works both as a shortcut and in the bracketed intents[...] form
  • The legacy URL query grammar is now internally frozen: new URL capabilities land as config keys or intent shortcuts instead of new legacy parameters. No behavior changes — every existing URL keeps working exactly as before.
  • Offline archives now inline @import'ed stylesheets (e.g. Google Fonts) into the custom CSS and bundle the font files they reference, so custom fonts load when a copy is served locally or without network.
  • Internal: opt-in timing diagnostics for schema validation during config load, logged (throttled, cumulative) on the efp:config:validate debug namespace. No functional or public SDK API changes.
  • Fix floor plans and offline copies failing to load for events whose drawing comes from the V2 converter, which encodes mesh geometry as 3-component [x, y, z] vertices — these are now accepted during config validation (previously rejected, breaking both live loads and offline copy generation).
  • Fix floor plans failing to load for events whose search/filter button config omits the visible flag on one or more buttons.
  • Offline archives now render custom fonts correctly when a plan's Custom CSS pulls the font in with @import url(<font-file>) (a common authoring shortcut) alongside its @font-face rule. Previously the exported copy inlined the font file's raw bytes into the stylesheet, corrupting it so no custom font applied offline — while the same plan rendered fine online. Such an @import is now recognized as a non-stylesheet and dropped (matching browser behavior); the font still loads offline from the @font-face's own bundled URL.
  • Floor plans generated by newer converters no longer lose their SVG layers: layer files that carry only suffixed drawing globals (__fpBooth, __fpPathsBooth) now render — previously every non-default layer (booths, elements, background) disappeared from the plan. Event-data schemas also gained the booth status ('onhold' | 'reserved'), booth holdColor, and exhibitor logoInBooth fields the runtime reads.
  • Deep links that combine an exhibitor slug with configuration or intent parameters (e.g. ?my-exhibitor&allowConsent=false) select the exhibitor again instead of opening the search panel with its display name as search text. True multi-slug share links (?exh1&exh2, also in the %26-encoded form) keep showing readable exhibitor names.
  • Embedded floor plans with ignoreQuery now honor the manifest/options camera, visibility, presentation flags and heatmap mode (previously dropped together with the URL handling). applyParameters() now applies the full canonical query — camera[…], visibility[…], consent and intents (both intents[…] and shortcut keys like selectBooth) — and a query consisting only of config/intent keys no longer closes the open panel. Switching between the 2D and 3D views no longer re-applies the boot camera or replays the boot URL over the visitor's current state. The in-app back button no longer leaves orphan entries in the browser history.
  • More resilient deep links and embeds: a malformed percent-escape in the URL (e.g. ?100%booth) no longer breaks startup or permanently stops URL synchronization, and ?debug=1 under frozen URL writes (offHistory embeds, heatmap mode) no longer triggers an endless reload loop.
  • More resilient URL handling and startup: a blank numeric URL parameter (e.g. ?camera[bearing]=) is ignored instead of becoming 0, a failing deep-link intent is logged and skipped instead of breaking the page, a config without a floor plan drawing now shows the event-not-found screen instead of an endless spinner, and legacy event data with null booth/exhibitor/category lists loads with empty lists.
  • Hardened startup: a transient network failure while fetching event data no longer sticks until reload, floor plans load again on Chrome 66-72 WebViews, embeds boot without localStorage access (e.g. cookie-blocked iframes), and a malformed bracketed URL index can no longer hang the page.
  • Heatmap mode is now a config node: use ?heatmap[variant]=yah&heatmap[kiosk]=true (or heatmap in the manifest) to engage it; the legacy ?heatmap=true&type=yah&subtype=kiosk links keep working unchanged.
  • Internal cleanup of direct URL readers with provenance notes; the previously undocumented ?layer= query parameter (initial floor by its floor-selector short label) is now documented in the query-parameters reference.
  • The floor plan's back button now uses the browser's real history: pressing it is the same as the browser's own back button, and browser back/forward stay consistent with in-app navigation.
  • Category, POI-type and exhibitors filters can now be set from any config layer via the filters node and the ?filters[…] URL form; the legacy categories=/poiType(s)= links keep working.
  • Viewer-mode, preview-mode and UI-scale preferences seeded from the URL (?viewermode=, ?previewMode=, ?uiscale=) are now stored as schema-typed efp-* localStorage settings (efp-viewerMode, efp-previewMode, efp-uiScale); existing ___* values keep working and migrate automatically at load.
  • Fixed a load failure on URLs that use the same query key in both scalar and bracketed form (e.g. ?consent=granted&consent[x]=1): the malformed key is now tolerated and dropped like any other invalid URL input instead of breaking the floor plan boot.

3.11.12 (2026-07-15) ​

🩹 Fixes ​

  • Fix wayfinding lint compatibility with type-aware ESLint.
  • Internal: extracted the framework-neutral wayfinding engine, runtime, and scene renderer into a new @expofp/wayfinding package behind a single createWayfinding() entry point. No functional or public SDK API changes.
  • Restore custom fonts and customCss styles when the floor plan renders inside a shadow root: @font-face and :root custom properties (e.g. --expofp-font-face) are now injected at the document level so custom fonts load again.

3.11.11 (2026-07-06) ​

🩹 Fixes ​

  • Internal tooling: repair ESLint config so type-aware linting actually runs, and apply the resulting type-safety cleanups. No functional/API changes to the SDK.

3.11.10 (2026-07-02) ​

🩹 Fixes ​

  • Update the floor plan rendering engine to 3.2.5.

3.11.9 (2026-07-02) ​

🩹 Fixes ​

  • Hide the viewer event selector when no leave-event handler is configured.

3.11.8 (2026-07-01) ​

🩹 Fixes ​

  • Track clicks on advertised exhibitor logos in the banner.

3.11.7 (2026-06-30) ​

🩹 Fixes ​

  • Update URL for PDF API

3.11.6 (2026-06-30) ​

🩹 Fixes ​

  • Internal: refactor the event badge and heatmap legend into self-contained presentational UI components, decoupled from floorplan internals. No SDK-facing or runtime changes.

3.11.5 (2026-06-29) ​

🩹 Fixes ​

  • Internal wayfinding refactor: the renderer layer no longer depends on the floorplan-local renderer module — scale/roll/click are driven from the app via a small injected renderer port, and route-line animation moved into wayfinding. No functional or API changes.

3.11.4 (2026-06-29) ​

🩹 Fixes ​

  • Fix passed route segments rendering as active after switching to an already-passed floor on a multi-floor route.
  • Improve keyboard navigation and screen-reader support for the mobile map/list toggle button, and stop a dismissed banner from briefly reappearing. Ship complete TypeScript type declarations for the lazy-loaded QR code component.

3.11.3 (2026-06-29) ​

🩹 Fixes ​

  • Fix browser tab freeze when navigating away from a page while a route animation is running.

3.11.2 (2026-06-29) ​

🩹 Fixes ​

  • Accessibility and keyboard-navigation improvements: Escape now dismisses the map layers panel, the level selector has better keyboard navigation and screen-reader labels, and sidebar buttons announce their state correctly. No public API changes.

3.11.1 (2026-06-29) ​

🩹 Fixes ​

  • Booths rotated to arbitrary angles now respond to hover and clicks across their true rotated outline. Previously only right-angle rotations (multiples of 90°) were handled — at any other angle a booth rendered rotated but reacted across its unrotated, upright footprint. When booths overlap, a hidden booth no longer intercepts hover or clicks meant for a visible booth beneath it.

3.11.0 (2026-06-29) ​

🚀 Features ​

  • Add a hideBoothBadges flag to hide booth number badges. Booth number badges also render again on booths that display an exhibitor logo.

3.10.2 (2026-06-26) ​

🩹 Fixes ​

  • Improve MapLibre map rendering and camera behavior for large, rotated, and slightly inconsistent floor plans. The map view now fits and pans more reliably, keeps venues at their intended orientation, avoids squashing from imperfect geo anchors, keeps booth labels scaled and upright, and uses a Mapbox Streets-like no-key basemap theme for online and generated offline maps.

3.10.1 (2026-06-24) ​

🩹 Fixes ​

  • The wayfinding route engine is now built once per floorplan and shared, instead of being rebuilt on every route check. As a result, checkRoutes() now requires the floorplan to be initialized first: if it is called before wayfinding is ready, it logs a warning and skips the check instead of building routes on its own.
  • Internal wayfinding code-quality cleanup (stricter type-checking and linting); no functional or API changes.

3.10.0 (2026-06-24) ​

🚀 Features ​

  • Add a busRoutes flag to opt in to live bus/transport routing. Bus routing is now off by default, so plans without transit routes no longer make an extra network request on load.

3.9.0 (2026-06-24) ​

🚀 Features ​

  • Built-in search filter buttons (Bookmarks, Visited, Categories, Sessions, Exhibitors, Guided Tours) now follow the viewer's selected language instead of always showing in English, and the filter bar's scroll controls gained translated accessibility labels. Organizer-named buttons (POI types, links, custom labels) stay as authored, with no missing-translation console warnings.

3.8.0 (2026-06-23) ​

🚀 Features ​

  • Introduce the @expofp/geometry package — a shared geometry toolkit with point/line/box/rect/polygon/mesh primitives and helpers (point-on-segment projection, bounding box from a point set, polygon area & point-in-polygon, segment intersection, angle normalization, convex-ring polygons) plus a geographic (geo) module for haversine distance, bearing, destination point, and local↔GPS projection. @expofp/floorplan and @expofp/offline now consolidate their internal geometry onto it; their public APIs are unchanged.

3.7.17 (2026-06-23) ​

🩹 Fixes ​

  • Fixed wayfinding so a route between two locations on the same floor no longer detours through another floor.

3.7.16 (2026-06-22) ​

🩹 Fixes ​

  • Refactor the Modal into a presentation/container architecture with improved accessibility (required dialog name, focus trap, scroll-lock restore). No changes to the public SDK API.

3.7.15 (2026-06-22) ​

🩹 Fixes ​

  • Improve link sharing and localization: copying the floor plan link now works on older Android WebViews, and Facebook/X/LinkedIn share links stay intact when the floor plan URL carries its own query parameters. Event, language, and rebooking labels update immediately on language switch, and rebooking selection and notes are preserved reliably. Remaining changes are an internal refactor of presentational UI components with no API changes.

3.7.14 (2026-06-22) ​

🩹 Fixes ​

  • Fix Storybook component tests failing to run under Babel 8 (legacy decorators option).
  • Internal: refactor the search Autocomplete into a reusable, fully-controlled UI component with improved keyboard and screen-reader support — no SDK-facing changes.

3.7.13 (2026-06-22) ​

🩹 Fixes ​

  • Restore Storybook browser test builds under Babel 8 (CI no longer hangs)

3.7.12 (2026-06-22) ​

🩹 Fixes ​

  • Load device diagnostics lazily so they no longer add to the entry bundle.

3.7.11 (2026-06-22) ​

🩹 Fixes ​

  • Remove the window.efpEnv global.

3.7.10 (2026-06-22) ​

🩹 Fixes ​

  • Log a one-line device and environment summary (OS and version, browser, device model, viewport, language) to the console and expose it on window.efpEnv, so end users can copy it and send it to support when reporting issues.

3.7.9 (2026-06-22) ​

🩹 Fixes ​

  • Fixed the kiosk icon appearing too large. Kiosk mode now restores the camera to its configured position reliably, even when a reset is triggered several times in quick succession. Analytics events fired outside kiosk mode no longer carry a stale kiosk ID.

3.7.8 (2026-06-18) ​

🩹 Fixes ​

  • Viewer mode: the search box home button now uses a solid icon with a highlighted style.
  • Maintenance: upgrade the build and test toolchain (Nx 23, Vitest 4, TypeScript 6, Babel 8) and switch to Vite's native tsconfig path resolution. No changes to the public API or runtime behavior.

3.7.7 (2026-06-17) ​

🩹 Fixes ​

  • Standardize type-only imports to inline import { type X } syntax. Internal code-style change with no impact on runtime behavior or the published API.

3.7.6 (2026-06-17) ​

🩹 Fixes ​

  • Fix maps misrouting when opened via links carrying analytics parameters (Google Analytics gl/_ga, ad-click ids, utm*).

3.7.5 (2026-06-17) ​

🩹 Fixes ​

  • Fix wayfinding animation by updating the underlying rendering engine to its latest release.

3.7.4 (2026-06-16) ​

🩹 Fixes ​

  • Fix rebooking links sometimes opening as a regular floor plan instead of rebooking mode. The floor plan state could initialize more than once and corrupt exhibitor data through a race condition; state now initializes exactly once after data loads, so rebooking mode activates reliably.

3.7.3 (2026-06-16) ​

🩹 Fixes ​

  • Fix kiosk coordinates not being saved to the database when an existing kiosk is edited. Editing a kiosk's position, heading, scale, or camera now updates the stored record instead of only saving locally.

3.7.2 (2026-06-16) ​

🩹 Fixes ​

  • Category search buttons now display the correct exhibitor count and highlight matching booths on the floor plan when selected.

3.7.1 (2026-06-15) ​

🩹 Fixes ​

  • Fix kiosk mode so the map can be zoomed and clicked again — the kiosk panel overlay no longer blocks interaction with the map underneath it.

3.7.0 (2026-06-15) ​

🚀 Features ​

  • Add getGeoConfig() to read the map's geographic configuration: its bearing (degrees clockwise from north; 0 when the map is north-aligned) and the GPS anchor points (p0, p1, p2) used to georeference the plan. Returns null when the plan has no GPS configuration.

3.6.8 (2026-06-12) ​

🩹 Fixes ​

  • Fix icons in bus routes by updating the rendering engine.

3.6.7 (2026-06-11) ​

🩹 Fixes ​

  • Update the rendering engine to its newest release.

3.6.6 (2026-06-11) ​

🩹 Fixes ​

  • Update the rendering engine to the latest version.

3.6.5 (2026-06-11) ​

🩹 Fixes ​

  • Allow swapping the route start and end points in wayfinding even when one of them has not been chosen yet.

3.6.4 (2026-06-10) ​

🩹 Fixes ​

  • Fix multibooth wayfinding to route from the selected exhibitor instead of the first one listed alphabetically; minor booth-color and detail-panel UI refinements.

3.6.3 (2026-06-10) ​

🩹 Fixes ​

  • Open the debug panel with 7 quick taps in a screen corner — works on kiosks and touch devices without a keyboard

3.6.2 (2026-06-10) ​

🩹 Fixes ​

  • Update bundled Sentry error-monitoring dependency to 10.57

3.6.1 (2026-06-10) ​

🩹 Fixes ​

  • Maintenance: internal build and lint tooling updates. No changes to published package behavior.

3.6.0 (2026-06-09) ​

🚀 Features ​

  • Wayfinding routes can now start from or end at any point on the map, not only booths.

3.5.2 (2026-06-09) ​

🩹 Fixes ​

  • Keep booth labels oriented correctly when rotating MapLibre maps.

3.5.1 (2026-06-08) ​

🩹 Fixes ​

  • Expose a window.__expofpReady latch alongside the expofp:ready event so listeners that attach after the plan is ready can still detect readiness.

3.5.0 (2026-06-08) ​

🚀 Features ​

  • Add data.flags.customSetKiosk to override the kiosk-mode trigger command; improve search to match mid-string fuzzy hits and handle HTML tags and casing in description fallback.

3.4.5 (2026-06-05) ​

🩹 Fixes ​

  • Improve the debug settings panel layout so each setting's control sits beside its label, with text inputs filling the available width, and the controls and action buttons reflow onto their own lines on narrow screens.

3.4.4 (2026-06-05) ​

🩹 Fixes ​

  • Fix the maplibre debug override setting.

3.4.3 (2026-06-05) ​

🩹 Fixes ​

  • Fix the floor plan appearing blank in some Android WebView embeds, where the map could collapse to zero size.

3.4.2 (2026-06-05) ​

🩹 Fixes ​

  • Fix the on-screen debug console not opening on Android and other touch devices: the activation shortcut is now recognized from soft-keyboard (IME) input, not only physical keyboards.

3.4.1 (2026-06-04) ​

🩹 Fixes ​

  • Sort the debug settings panel alphabetically so options are easier to find.
  • Add a debug settings override to force the experimental Maplibre map on or off (or inherit the default), independent of event data.
  • Improve accessibility across floor plan UI components and fix minor rendering issues in speaker and entity lists.

3.4.0 (2026-06-04) ​

🚀 Features ​

  • Add Maplibre-based map rendering with offline tile support and related floorplan integration updates.

3.3.8 (2026-06-04) ​

🩹 Fixes ​

  • Sync with upstream main: refactor internal UI components into a presentation/container architecture. No public API changes.

3.3.7 (2026-06-03) ​

🩹 Fixes ​

  • Update bundled and peer dependencies (Sentry error reporting and React) to their latest patch releases for stability and bug fixes.

3.3.6 (2026-06-03) ​

🩹 Fixes ​

  • Improve rebooking-mode UX (exhibitors panel alignment, close button, and reset behavior), focus the blue dot when targeting a position via URL parameter, and rename the kiosk location label to "Your Location".

3.3.5 (2026-06-03) ​

🩹 Fixes ​

  • Internal: add Storybook dev setup with CI smoke tests — no SDK-facing changes.

3.3.4 (2026-06-02) ​

🩹 Fixes ​

  • Fix map rendering so guided-tour pathway layers stay visible above booth badges

3.3.3 (2026-06-02) ​

🩹 Fixes ​

  • The Intercom support chat no longer appears on kiosk displays.

3.3.2 (2026-05-31) ​

🩹 Fixes ​

  • Debug overlay now displays as a translucent, blurred panel over the floor plan instead of a solid black screen, keeping the floor plan visible underneath while debugging.

3.3.1 (2026-05-29) ​

🩹 Fixes ​

  • Show an "Event not found" message when an event's data cannot be loaded, instead of leaving a blank or broken floor plan.

3.3.0 (2026-05-29) ​

🚀 Features ​

  • Danish (da) is now available as a UI language for the floor plan viewer.

3.2.16 (2026-05-28) ​

🩹 Fixes ​

  • Removed an unused jspdf runtime dependency, fixing installation failures for SDK consumers on pnpm 11. Workspace tooling also upgraded to pnpm 11.

3.2.15 (2026-05-28) ​

🩹 Fixes ​

  • Update internal dependencies and build tooling to their latest compatible versions.
  • Sync with upstream main: tour launch on mobile collapses overlay to medium.

3.2.14 (2026-05-20) ​

🩹 Fixes ​

  • Internal refactor: extract pure UI primitives (Alert, Badge, Button, etc.) into separate modules — no functional changes for SDK consumers.

3.2.13 (2026-05-19) ​

🩹 Fixes ​

  • Add a per-event flags bag on data.flags (typed via FloorPlanFlags). enableExperimentalRerouting now reads from data.flags.enableExperimentalRerouting, falling back to the legacy fpGeo.properties.config.enableExperimentalRerouting so existing events keep working.

3.2.12 (2026-05-19) ​

🩹 Fixes ​

  • Floor plan host elements no longer receive the auto-applied expofp-floorplan-default class. The class was an internal marker (debug overlay) and was never part of the documented public API. If your CSS targeted .expofp-floorplan-default, switch to a selector you control on the container element (e.g. an #id or your own class).

3.2.11 (2026-05-19) ​

🩹 Fixes ​

  • Embedding the floor plan in a custom container no longer requires !important in your CSS. Default layout styles (position, inset, width, height) are now applied via a low-specificity stylesheet, so any #floorplan { ... } rule in your page beats the SDK's defaults naturally. Useful for in-flow embeds.

3.2.10 (2026-05-15) ​

🩹 Fixes ​

  • Visible-area calculation now respects camera rotation; previously a rotated map could over-report which booths were on-screen.

3.2.9 (2026-05-13) ​

🩹 Fixes ​

  • Restore booth polygon-bounds in wayfinding graph candidate search; refine free-license banner typography.

3.2.8 (2026-05-12) ​

🩹 Fixes ​

  • Fix map overlay visible-rect recalc and wayfinding transition selection; remove legacy ?yah= URL parameter (Kiosk default still supported).

3.2.7 (2026-05-11) ​

🩹 Fixes ​

  • Fix: Isolate the Intercom launcher in a shadow DOM to prevent floor-plan styles from leaking into the chat widget.

3.2.6 (2026-05-07) ​

🩹 Fixes ​

  • Fix: passing focus=false when reporting current position no longer triggers camera refocus or reroute.

3.2.5 (2026-05-07) ​

🩹 Fixes ​

  • Fix multi-floor bookmark/visited highlight and camera fit, blue-dot pan when GPS is outside the area map, and make wayfinding rerouting opt-in via fpGeo.

3.2.4 (2026-05-06) ​

🩹 Fixes ​

  • Floorplan now fills the dynamic viewport on mobile (no jump as the browser chrome collapses) and disables the page-level pull-to-refresh gesture so it cannot interrupt floorplan interactions on iOS Safari.

3.2.3 (2026-05-06) ​

🩹 Fixes ​

  • Silence a benign React 19 dev warning from mobx-react-lite at the SDK entry.

3.2.2 (2026-05-06) ​

🩹 Fixes ​

  • Avoid a stray React dev warning when entering kiosk edit mode.

3.2.1 (2026-05-06) ​

🩹 Fixes ​

  • Internal QR code refactor (no behavior change).

3.2.0 (2026-05-06) ​

🚀 Features ​

  • Add selectAccessibleRoute() to restrict wayfinding to accessible-only segments.

3.1.16 (2026-05-06) ​

🩹 Fixes ​

  • Debug panel: custom-setting registration moved from window.efpDebug.settings[key] = schema to window.efpDebugUi[key] = schema. The label option has been removed — the setting's key is now used as the heading text in the panel.
  • Fix the floor plan failing to load on Safari 14 due to a SyntaxError in the JSON import helper. The loader now detects browsers without dynamic-import attribute support and falls back to fetch.

3.1.15 (2026-05-06) ​

🩹 Fixes ​

  • Bump @expofp/renderer to 3.1.6

3.1.14 (2026-05-05) ​

🩹 Fixes ​

  • Debug mode now uses the namespaced efp:debug localStorage key with true/false values (previously debug with 1/0). The toggle is registered with the window.efpDebug.settings registry for the debug panel.

3.1.13 (2026-05-05) ​

🩹 Fixes ​

  • Debug panel: register custom settings from any code via window.efpDebug.settings — no @expofp/debug import required.

3.1.12 (2026-05-05) ​

🩹 Fixes ​

  • Cookie consent banner: restore bottom-left placement on desktop

3.1.11 (2026-05-05) ​

🩹 Fixes ​

  • Viewer mode: refined Search and Menu styling, smoother overlay animation

3.1.10 (2026-05-05) ​

🩹 Fixes ​

  • Fix: Log tab now correctly captures debug npm output in production browser bundles. (The bundler had been inlining the console-wrap install module so the wraps applied after debug npm captured its console references; now the wrap install is forced into its own chunk that evaluates first.)

3.1.9 (2026-05-05) ​

🩹 Fixes ​

  • Debug panel:
    • New Log tab captures console.log/debug/info/warn/error output with %c color formatting preserved, including styled output from the debug npm library. Capped at 5000 entries (oldest evicted first).
    • New "Debug namespaces" text input accepts wildcards like efp:* and applies them immediately without reload.

3.1.8 (2026-05-04) ​

🩹 Fixes ​

  • Map: keep booth logos within bounds when the floor plan is rotated.

3.1.7 (2026-05-04) ​

🩹 Fixes ​

  • Traffic: silently ignore 204 / non-OK responses from /v1/routes when there are no bus routes for the plan.

3.1.6 (2026-05-04) ​

🩹 Fixes ​

  • Update bundled @expofp/renderer to 3.1.4.

3.1.5 (2026-05-04) ​

🩹 Fixes ​

  • Restore debug overlay styling when Shadow DOM is enabled

3.1.4 (2026-04-30) ​

🩹 Fixes ​

  • Simplify search placeholder, refresh translations, and improve language switcher accessibility

3.1.3 (2026-04-30) ​

🩹 Fixes ​

  • Lazy-load Intercom messenger and gate it to ExpoFP-hosted floor plans (skipped offline). Heatmap mode now displays markers.

3.1.2 (2026-04-29) ​

🩹 Fixes ​

  • Pin ESLint plugins to versions compatible with @nx/eslint (ESLint 9)
  • Update all dependencies to their latest compatible versions, including build tooling.

3.1.1 (2026-04-29) ​

🩹 Fixes ​

  • Link @expofp packages on npm to the developer docs site, and add a quickstart README to @expofp/floorplan.

3.1.0 (2026-04-29) ​

🚀 Features ​

  • Add Intercom messenger integration with subscription-based gating; refresh free banner ribbon and cookie consent UX

3.0.4 (2026-04-28) ​

🩹 Fixes ​

  • Fix locales not loading when SDK is imported from a redirecting CDN URL (e.g. unpkg.com/@expofp/floorplan@VERSION)

3.0.3 (2026-04-28) ​

🩹 Fixes ​

  • Redo upstream main merge to fix runtime regressions (e.g., Menu rendering as blank screen on events with register links).

3.0.2 (2026-04-28) ​

🩹 Fixes ​

  • Fix traffic visualization crash before renderer init and adjust overlay sizing on booth selection.

3.0.1 (2026-04-24) ​

🩹 Fixes ​

  • Fuzzy search: tighter match threshold and position-aware scoring for more relevant results

3.0.0 (2026-04-24) ​

🩹 Fixes ​

  • Adopted a two-channel release model: regular releases ship to the @latest dist-tag; a separate @stable dist-tag will be maintained as a soak-delayed pointer for production-critical installs (moved manually after a bake period).

3.0.0-alpha.22 (2026-04-24) ​

🩹 Fixes ​

  • Docs: grammar polish across guides; fixed malformed bookmarks tables in the query-parameters reference; clarified the search example to avoid clashing with ?b= bookmarks.
  • Docs: clearer v2 → v3 migration guide with side-by-side before/after; examples and guide snippets now import @expofp/floorplan directly (no more @next dist-tag).

3.0.0-alpha.21 (2026-04-23) ​

🩹 Fixes ​

  • Browser bundle's index.js now contains the main module directly instead of re-exporting from an intermediate chunk, reducing one HTTP request on direct browser loads

3.0.0-alpha.20 (2026-04-23) ​

🩹 Fixes ​

  • Booth badges now support noLabels booths with exhibitors, respect hideExhibitorBoothNumber, render above plan layers, and keep consistent size on retina displays; search matches non-consecutive query terms within a field

3.0.0-alpha.19 (2026-04-15) ​

🩹 Fixes ​

  • feat(telemetry): respect Retry-After on throttling, plus attribution and overflow fixes
    • Telemetry: Retry-After handling — The SDK now pauses outbound telemetry when the collector responds with HTTP 429 or 503 and a Retry-After header, honoring both seconds and HTTP-date formats (capped at 5 minutes). Traffic automatically backs off when the telemetry endpoint is throttled or degraded instead of retrying in a tight loop.
    • Telemetry: event storage cap — Failed batches merged back into pending storage are now capped at 1,000 events, preventing unbounded localStorage growth if the telemetry endpoint stays unreachable for an extended period.
    • Telemetry: cross-session attribution fix — Events persisted in localStorage from a previous event/expo are now re-attributed to the current expo on send, so switching between expos on the same device no longer mixes analytics across events.
    • Telemetry: large-batch delivery fix — Large accumulated batches no longer silently fail to send; the keepalive request flag is omitted for payloads above ~63KB, and payload size is measured in bytes (via TextEncoder) so multi-byte characters are counted correctly.
    • Kiosk: zoom stability — Fixes a NaN zoom level when a kiosk configuration specifies mapPtScale of zero; zoom is now left unchanged in that case instead of producing an invalid value.

3.0.0-alpha.18 (2026-04-15) ​

🩹 Fixes ​

  • fix: favicon link in floor plan HTML and custom CSS with Shadow DOM
    • Favicon — index.html includes the favicon link in the correct place for the dev entry.
    • Custom CSS with Shadow DOM — loadCustomCss resolves the style root when the map runs inside a shadow root.

3.0.0-alpha.17 (2026-04-14) ​

🩹 Fixes ​

  • feat: virtual line distance in routing cost and completed reactive i18n
    • Virtual line distance in routing cost — When a virtual line has a virtualLength value configured per-line in the designer, the pathfinder uses that as the edge cost instead of treating virtual links as free (cost 0). Multi-floor routes now prefer staying on the same floor when virtual lengths are set, producing more natural directions. Explicit 0 is still honored.
    • Reactive i18n refactor completed — The LanguageStore has been removed; locale state now lives in a single source of truth in utils/i18n. RTL direction updates reactively when changeLanguage() is called, without any re-render hacks in the overlay.
    • Legacy language key auto-migration — Users with a locale saved under the old language localStorage key are read once on startup and migrated to the new efp-locale key, so existing installs retain the user's previous selection.
    • Public type rename: FloorPlanLanguage → Language — The language entity type exported from FloorPlanEntity has been renamed and narrowed to { readonly id: string; readonly name: string; readonly entity: { readonly type: "language" } }. Integrators that destructure language entities from search results or entity lists may need to adjust type imports.
    • Wayfinding module refactor — Wayfinding is now a self-contained module (src/wayfinding/) with a hexagonal (ports/adapters) architecture. Public API is unchanged; the refactor isolates pathfinding, routing, position tracking, and rendering behind clean interfaces so future extensions land without touching call sites.
    • Wayfinding stability fixes — Hotfix for an infinite loop on certain route configurations; event-specific rerouting disabled for the CloudNext26 layout where heuristic-based rerouting produced poor transitions.
    • New math utility — Shared helpers (toRadians, decreaseByPercentage) now live in utils/math.ts, replacing the removed utils/toRadians.ts. Not part of the public API.

3.0.0-alpha.16 (2026-04-09) ​

🩹 Fixes ​

  • feat: viewer app mode, event metadata panel, reactive translations, and route planner v2
    • Viewer app mode — New viewerMode option opens a full-screen menu with an event metadata panel; onLeaveEvent callback fires when the user exits, and the menu icon becomes a home icon while viewer mode is active
    • Event metadata panel — Shows event title, venue, and date range from data; displays a "Now" badge when the event is currently live and an "Ongoing" label when start/end dates are missing
    • Reactive translations — t() now re-renders UI automatically when changeLanguage() is called, so language switching updates every label without a manual refresh
    • expofp:ready DOM event — Dispatched on window when the floor plan finishes initializing (detail contains the floorplan instance), so integrators can listen instead of polling window.___fp
    • Route planner v2 — Multi-floor routes now show a floor selector; stop items display booth name plus a level badge; non-routable bookmarks no longer surface the route planner entry
    • Custom floor indexing — Honors floorIndex from data so events can define a custom floor ordering instead of relying on declaration order
    • Bookmarks: share button — Moved from the search box into the bookmarks panel, where sharing a saved set of booths makes more sense
    • FloorPlanBooth.title — Exposed as an optional field on search results so integrators can surface richer booth titles
    • reset() now fits bounds — Calling reset() re-centers the map on the full floor; in kiosk mode with a configured resetCameraFn, the kiosk camera hook runs instead
    • TouchHand indicator — Only shown in kiosk mode (previously appeared in all modes)
    • Wayfinding stability — Hotfix for an infinite loop on certain routes; fixes for floor-switching collisions and selector click issues
    • Floor index fix — Corrects floor index resolution for multi-floor plans
    • Blue dot layering — Current-position marker now resolves to the correct layer when the position specifies an explicit z
    • Modal rendering in Shadow DOM — Modal portal container now resolves correctly whether the floor plan is mounted inside a shadow root or the regular DOM
    • Route tracking deduplication — Stops firing duplicate analytics events on automatic route recalculation; events only fire on explicit user-initiated route resets

3.0.0-alpha.15 (2026-04-08) ​

🩹 Fixes ​

  • Publish Sentry source maps and release tags so integrator error reports resolve to original source and group by SDK release
  • Fix pathfinding failure that broke route calculation

3.0.0-alpha.14 (2026-04-01) ​

🩹 Fixes ​

  • Add native SDK compatibility helper for WKWebView bridge timing
  • Offline ZIP archives now nest all files under the expo name directory

3.0.0-alpha.12 (2026-03-31) ​

🩹 Fixes ​

  • Fix offline runtime entry path resolution for relative imports (7e188dfd)
  • Camera reset now fits map to visible bounds, route planner button in sidebar actions, and updated tour data (fa7486eb)

3.0.0-alpha.11 (2026-03-22) ​

🩹 Fixes ​

  • fix: remove ./ prefix from zip entry paths (9d0c0ef6)
  • Rename public API exports for clarity: niceFetch → fetchWithRetry, importJsonModule → importJson, importRuntimeJsonModule → importRuntimeJson, sha256Base62Truncated → shortHash, slugifyFilesystemUnique → safeSlugify (5c61e5be)

3.0.0-alpha.10 (2026-03-17) ​

🩹 Fixes ​

  • feat: route planner, optimized routing, lazy QR code, and pathfinding improvements (2efdcd3d)
    • Route Planner — Plan multi-stop routes from bookmarks or custom selections, with automatic start-point detection and drag-to-reorder stops
    • Optimized Multi-Stop Routing — getOptimizedRoutes() SDK method uses nearest-neighbor + 2-opt heuristic to minimize total travel distance across waypoints
    • Lazy QR Code Loading — QR code component is now lazy-loaded, reducing initial bundle size
    • Pathfinding Improvements — Virtual (non-physical) route segments are now penalized in pathfinding to prefer real walkable paths