Install and set up props
The generated props of every element on Install and set up. The guide is where they are explained; this is the whole surface.
MountayaElementsProvider
mapMountayaMap | null
The map the controls drive, when there is one.
Null until it has been constructed and loaded. Omitted, it is the enclosing provider's map, which is what lets a surface that builds one publish it by nesting a provider that states nothing else. A subtree that genuinely holds no map under a provider that does says so with map={null}.
clientItinerarySource | null
The client an element resolves an id through, when it is handed one instead of geometry.
Nothing in this package fetches. An element hands this to fetchItinerary, which calls a method on it: the arrangement MountayaMap already has with its own client, and the reason there is one credential, one retry policy and one error taxonomy across the family rather than two that drift.
Typed as the narrow ItinerarySource rather than as the whole client: a prop that accepted everything would let an element reach anything, and the next element would. A Mountaya instance satisfies it structurally, so a caller passes theirs straight in.
Optional, and separate from map on purpose. <ItineraryProfile> given segments needs neither; given an itineraryId it needs this and still no canvas, which is what keeps the element renderable in a dashboard card, a report or a print view.
controlIconsIconProvider
Glyphs for the map controls: zoom, compass, geolocate, the panel toggles.
Defaults to the enclosing provider's table, and to the bundled Lucide set outside one. An application holding a Nucleo licence passes its own table here, keyed by the same roles, and gets pixel parity with Mountaya's studio.
Compared member by member, each function by its identity: a copy written in the JSX ({ ...licensedIcons }) holds the same functions and re-renders nothing below the provider. Two functions that draw the same shape are not comparable short of calling them, so a provider whose functions are built at each render re-renders every element under this one and re-parses every glyph they draw: build yours at module scope.
uiIconsIconProvider
Glyphs for @mountaya/studio-react: the studio surfaces, as distinct from the map controls above. Defaults to controlIcons when this provider states one, and otherwise to the enclosing provider's.
It is a second seam and not a second table on the first because a set has one paint mode, and these two surfaces do not share one. A control sits on a map: it is a solid shape on a photographic background, drawn from a filled family so it reads at any zoom over any terrain. A menu item sits on a panel beside text, and is drawn from an outline family so it weighs the same as the words next to it. Mountaya's own studio draws them that way, and a design system that has one icon set for chrome and another for menus is the normal case, not the exotic one.
Painting either family the other way is the failure the paint field exists to prevent, and it does not throw: a filled glyph stroked draws a hairline outline of its silhouette, an outline glyph filled draws a blob. Both survive review as "the icons look off".
Defaulting to controlIcons is therefore a convenience for a consumer with ONE family, not a suggestion: passing a filled set here draws Mountaya's menus in blobs.
A set answers every role of UI_GLYPHS on @mountaya/elements/icons, which names each glyph the studio draws from this seam, its menu actions among them. A role the set leaves out draws nothing, with no error.
markerIconsIconProvider
Glyphs for the PLACES an element draws: the waypoint marks on an elevation curve.
The third seam, and the one that is not about chrome at all. controlIcons and uiIcons are two families of ROLES (zoom in, merge, rename), where this is a family of THINGS: a summit, a refuge, a water point, a car park. An itinerary states one per waypoint out of a closed vocabulary, so the set answering them is chosen by what your data says rather than by what your product looks like, and WAYPOINT_GLYPHS on @mountaya/elements/icons is that list.
It falls back to the enclosing provider's MARKER set rather than to controlIcons, which the two above do not, and the asymmetry is the whole reason it exists: a control set answers zoom-in and knows nothing about a refuge, so defaulting to it would draw every place on every curve as the same fallback pin, in the one place a reader is looking for the difference.
Same paint rule as the pair above: a set has one paint mode, and this one is drawn at fourteen pixels inside a coloured disc, so an outline family is the safe default and a filled family is a legitimate choice for a licensee who has one.
languageMapLanguage
The language the elements read in. Defaults to the enclosing provider's, and to English outside one.
English is built in, and {@link translations} holds every other language the page imported. The rest of MAP_LANGUAGES is accepted and falls back to English, so a consumer can select the same language here as they do for the map's labels and fill the gap through strings rather than reshaping their tree around which languages happen to be translated. A language Mountaya translates and the page did not import reads in English and says so once in development.
translationsTranslations<ElementsStrings>
The elements' words in each language beyond English that the page imported, keyed by language: { fr: frElementsStrings } from @mountaya/elements/i18n/fr. Defaults to the enclosing provider's, and to English alone outside one.
Compared by its members, so a set written inline in the JSX resolves once.
stringsElementsStringsOverrides
Copy overrides, merged onto the selected language. Anything omitted keeps its default.
Omitting this prop entirely inherits the enclosing provider's resolved bundle, so a nested provider adding a map keeps a host's wording. Stating it resolves from the language's base rather than layering onto the outer's: a provider that states its copy is stating it.
Either shape: a flat PartialElementsStrings overrides regardless of language, and a per-language record ({ fr: { controls: … } }) overrides one language and leaves the rest alone, which is how a consumer ships a language the elements do not carry. One shape or the other, never both: one key decides the shape, so the sections of an object that named a language beside them would be folded in no language.
Compared by CONTENT, so the documented inline form (strings={{ controls: … }} written straight into the JSX) costs one shallow walk per render rather than a full re-render of the map chrome. A formatter has no content to compare and is compared by identity: one written inline is a new function at each render, and its readers render again with it, so a formatter that reads its host's state words the state as it stands. Its readers are the elements whose words hold a formatter, <WaypointCard> among them, and a caller of useMountayaStrings. An element that words no formatter is handed one bundle across those renders and renders for none of them. A formatter declared at module scope is one function and moves nothing.
localestring
The locale a number, a date and a relative moment are WRITTEN in. Defaults to language.
A language decides which words a surface says; a locale decides the thousands separator, the calendar, whether a date reads day-first and where the percent sign goes. A Swiss product reads French words with de-CH grouping. See MountayaI18n of @mountaya/elements/i18n, which is the same three fields as one object: the shape @mountaya/studio-react's surfaces take, and the one a port declares once rather than three times.
tokensElementTokens
Overrides for the --mtya-* custom properties every element under this provider is drawn with. Merged onto the defaults, so an override naming one token leaves the rest alone.
State them ONCE here rather than per element, which is what this prop is for: an element root ASSIGNS its own token block rather than inheriting one (deliberately, so a published package never writes to :root), so a declaration on an ancestor is shadowed and does nothing. The provider hands these down and each root merges them into its own style.
A per-element style still wins over these, which is the order a consumer expects: the specific setting beats the general one.
Compared by CONTENT, as strings is, so the inline form tokens={{ "--mtya-accent": … }} re-renders nothing below the provider while it states the same values.
elementsTokens is the list, with each default. There is deliberately no colorScheme prop beside this: the scheme is data-mtya-color-scheme on an ancestor the HOST owns, and boundary.test.ts bans this package from ever writing that attribute, because two sources for one fact is a bug at the render where they disagree. Set it in your own stylesheet; the README shows the line.
paintMapPaintOverrides
Overrides for what the MAP draws: the itinerary stroke, its casing, the layer ranks.
The counterpart to {@link tokens}, and it has to be a separate seam rather than more custom properties: MapLibre evaluates paint expressions inside its own renderer against no DOM element, so a var(--mtya-accent) arrives as a string it cannot read and the layer draws in MapLibre's fallback. The tokens theme the chrome AROUND the canvas; this themes what is drawn IN it.
Folded per key through the same merge the strings use, so { itinerary: { casingColor } } changes the halo and leaves every width stop, dash and stacking rank where they were.
Compared by CONTENT, as tokens is, so an override written inline re-renders nothing below the provider while it states the same values.
childrenReactNode