Show a map with controls
MapView draws the map. MapControls is the floating stack over it, and every built-in button in that stack is a boolean you switch on. This page is about which control does which job. The Props tab lists all 19 components and every prop they take.
Render the map
MapView constructs the map, authenticates its tile requests, and reports the instance through onReady. Put that instance on MountayaElementsProvider and every control on the page drives the same map.
MapView fills its container, so give that container a height. Options are read once, at construction: a different credential needs a new key, not a changed prop. A session token that rotates is not a different credential: a client whose sessionToken is a function hands the map the token current at each request. terrain picks a base map from the layers manifest. mapStyle takes a complete style document of your own. style is DOM CSS. onReady fires after the style has loaded, which is the first moment the map accepts sources and layers. onDestroy fires for a map onReady handed out, just before that map is destroyed. A map torn down before its style loaded reports neither, which is what React StrictMode does to the first map of every development mount.
onError and onAccessRequired report what no call of yours could reject, and both are attached before the map makes its first request. onAccessRequired carries the status and the address of a 401, a 402 or a 403 on a tile, a sprite, a glyph, a style or the layers manifest. onError carries every other failure. A map that cannot be built at all throws to the nearest error boundary.
transformRequest replaces the tile transform the map derives from its client. Supply one at mount and MapView reads the prop at each request, so a transform rebuilt when a token rotates reaches the next tile. Whether there is one at all is the mount's to say: a transform first supplied on a later render is ignored, and a render that omits the prop keeps the last one supplied. maplibre takes MapLibre's own options: they are applied before the map's, so they add to them and replace none.
Packages and provider setup are on Install the SDK.
Add the control stack
Each built-in control is a boolean flag, off by default. children join the same stack, spacing and focus order.
openPanel decides who owns the open panel. Leave it unset and the stack owns its own, which is what rendering the built-in panels wants. Set it and the stack only reads it, then asks for a change through onTogglePanel and onClosePanel. disabled is read once and threaded to every control in the stack.
Every control is published twice, on the stack and flat: MapControls.Zoom and ZoomControl are the same component.
Pick the control for the job
CompassRose is the needle CompassControl draws, published so a compass of your own can reuse it. StudioControls belongs to the studio chrome rather than to this package.
Search places, itineraries and zones
SearchControl sits beside the stack rather than in it, because it is a panel-width bar rather than a square chip. It runs Mountaya's unified search through the client on the provider, and renders one list across every kind of result.
query and viewportScope are controlled independently. Pass one without its on* partner to freeze it, which pins a search to a single scope on purpose.
Look around with Street View
StreetViewControl is the handle a reader drags onto the map. It shows the coverage layer while the drag is live, so a reader can see where imagery exists. The imagery is Google's, so this control needs @googlemaps/js-api-loader and a Google Maps API key. Both are optional peers, which a consumer who never mounts the control never installs.
Pass exactly one of onOpen and onDrop. The props are a union, so passing both is a type error rather than a precedence question. onOpen keeps the default pipeline (unproject, corridor gate, coverage check) and takes the point that survived it. onDrop replaces that pipeline and answers for the drop itself; return false to bounce the handle. Coverage is a per-point request to Google, and bounds and minZoom are the cheap gates in front of it.
Choose terrains, points of interest and units
Three panels open from the stack, and each takes its options through a prop named after it.
LayersPanel picks the terrain and the overlays above it. isLocked is a display concern only, because the Tile API answers 403 whatever a picker shows. It exists so an application that knows the viewer's agreement can say so before the press.
PoiPanel toggles what the points-of-interest overlay draws. Pass groups to stand one row for several manifest keys, under your own label and glyph. Pass keys to show fewer built-in rows.
PreferencesPanel requires onPreferencesChange. A profile row, a cookie and a store are all reasonable homes for a reader's units. The panel picks none of them. Seed from defaultUnits (from @mountaya/elements/profile): every field of UnitFormatOptions is required, and a partial value round-tripped through storage reverts a reader's units without saying so.
Mount a panel on its own when it belongs in a sidebar or a settings drawer.
Set a handler and the default stops firing
Left unset, a control drives the map itself. Set an on* handler and the control becomes presentational: yours decides, and the built-in behaviour never runs. The two never both fire.
The two halves of the zoom pair are gated separately. A stack that overrides zoom-in keeps no live zoom-out whose default it never wired. The handlers that report are additive instead, and are named for it: onReady, onError, onAccessRequired, onLockedClick and onUnavailable report something the element still handles.
Two controls require their handler
DownloadControl and DirectionsControl take a required onClick, because they have nothing to drive. Exporting an itinerary and opening directions both end in a surface that belongs to your application. Neither can be guessed. Without a handler they would look live and do nothing.
Both stay live while the map is still loading. They act on an itinerary you already hold, not on something read off the canvas.
Build a control of your own
Five primitives are published so a control you add is indistinguishable from the ones Mountaya ships.
ControlButtonis the square chip.ControlGroupjoins adjacent chips into one raised surface.ControlTooltipdraws the control's name and the dimmed line under it.Glyphrenders one icon from the provider's set.OptionRowis a selectable line in a panel.
Icons, strings and theme come from the provider, so your control wears the same vocabulary as the built-ins. Customize the elements covers all three.
Next steps
Edit an itinerary
The editor map, its drawing engines, and the hooks that keep a studio in step.
Customize the elements
Swap the icon set, override strings, and match your own theme.
Use the map without React
The same map, driven imperatively from any framework.
Tile API
The terrains and overlays these panels switch between.