Get started

Studio surfaces props

The generated props of every element on Studio surfaces. The guide is where they are explained; this is the whole surface.

StudioControls

config

StudioConfig

required
embedded

boolean

default: false

fallbackItineraryId

string | null

default: null

The itinerary the download and directions controls act on when none is active.

A failed or unresolved detail read would otherwise leave both a dead button while the dialogs behind them can still answer for the configured id.

googleMapsApiKey

string

The Google Maps key the Street View handle bills its coverage check to.

Absent, the control renders nothing at all rather than a handle whose every drag ends in silence. That gate is the control's own: this passes the key and lets it decide.

streetViewHandle

ReactNode

SegmentList

activityDefaultSpeed

number | null

default: null

agentLockHint

string | null

default: null

emptyState

ReactNode

Shown in place of the rows when the chain is empty AND nothing is being drawn.

engineChoice

boolean

default: false

True when the activity can be authored either way, so the inserts offer the choice.

label

string

required
limit

number

A ceiling the host holds the list to, shown as a persistent count/limit beside the section label. The studio sets none: omitted, the label carries the bare count.

limitTooltip

string

The sentence the info glyph beside a limit explains it with, shown only with a limit.

mode

SegmentEditMode | null

required

The engine a single-engine activity authors in, as the first entry of availableEnginesForActivity names it. null for an activity the catalog gives no engine: nothing can be drawn for it, so the list renders no add control and no insert pill.

peerLockHint

(holderId: string) => string | null

Resolves a peer's id to the sentence a held row speaks with.

renderIndicators

(segmentId: string) => ReactNode

Host badges for one row, such as who is looking at the segment.

Called once for each segment while the slot's reference stands, and for every row again when the reference changes: the default row keeps what the slot drew for it until then. So a slot that reads a value outside its argument changes identity with that value, as a useCallback that lists it does.

renderRow

(row: SegmentListRow) => ReactNode

Renders one row, replacing the published one entirely.

The escape hatch for a host whose row is genuinely its own: Mountaya's carries live-awareness badges, a localized sentence per refusable verb, and a peer's display name resolved from an organization directory. Everything the list derived arrives resolved, so a custom row re-derives nothing and cannot disagree with the gutter beside it.

Omit it and the list renders the published row, which is the whole point of the default: units, renderIndicators and peerLockHint cover the ordinary host without one.

units

UnitFormatOptions

default: defaultUnits

unsavedHint

string | null

default: null

What a row the server has never seen says about itself.

activitySlug

string

The activity an inserted routed segment routes for.

itineraryId

string

required

The itinerary whose chain the list renders and whose verbs it dispatches.

segments

ItineraryViewSource["segments"]

required

The COMMITTED chain, in chain order.

SegmentList.AddButton

AddSegmentButton is the foot of the segment editor.

activitySlug

string

agentLockHint

string | null

default: null

engineChoice

boolean

default: false

insertLimitHint

string | null

default: null

mode

SegmentEditMode | null

required

The engine a single-engine activity opens in, as the first entry of availableEnginesForActivity names it. null for an activity the catalog gives no engine: nothing can be drawn for it, and the control renders nothing.

SegmentList.Row

SegmentRow renders one segment as a two-line editor row.

ascent

string

required
chain

SegmentRowChainOptions

color

string | null

deleteDisabled

boolean

distance

string

required
distanceMeters

number | null

durationSeconds

number | null

group

SegmentRowGroupActions

groupRail

SegmentRowGroupRail

indicators

ReactNode

mode

SegmentEditMode

required
name

string

required
reasonMessage

string | null

speed

number | null

activityDefaultSpeed

number | null

trailing

ReactNode

activitySlug

string

The router profile a directions edit routes under.

agentLockHint

string | null

The sentence a row shows while a run drives the studio, or null where none can.

itineraryId

string

The itinerary the row belongs to. Undefined for a draft's row, whose id is on no tile.

peerLockHint

string | null

The sentence a row shows while a peer holds the segment, or null where none can.

segmentId

string

required

The segment the row stands for.

segmentName

string

required

The segment's current name, which the rename opens on.

unsavedHint

string | null

The sentence a row shows while its segment is not saved yet, or null where none can be.

SegmentList.Seam

SegmentSeam is the hover gutter between two segment rows: a zero-height sibling of the rows carrying the pill that inserts a segment into this gap and the pill that merges the two rows it sits between. It is a sibling rather than something drawn inside a row because every row carries paint containment, which would clip an affordance offset above it; the styling lives in the list section's module, where the seam inherits the divider it replaces so the list's height is unchanged.

afterSegmentId

string | null

required
controlsEnabled

boolean

required
group

SegmentSeamGroup | null

required
groupChipDisabledHint

string | null

required
insertEngineChoice

boolean

required
insertMode

SegmentEditMode | null

required
merge

SegmentChainMerge | null

required

ReadOnlySegmentList

emptyState

ReactNode

emphasisSegmentIds

(segmentId: string) => readonly string[] | undefined

itineraryId

string

required
label

string

required
segments

ItineraryViewSource["segments"]

required
units

UnitFormatOptions

default: defaultUnits

WaypointList

agentLockHint

string | null

default: null

addControl

ReactNode

The add control, rendered below the list. Omitted on a surface that cannot add.

emptyState

ReactNode

iconLabel

(icon: ItineraryViewSource["waypoints"][number]["icon"]) => string

required

Names one icon in the reader's language, for the fallback a nameless waypoint shows.

label

string

required
peerLockHint

(holderId: string) => string | null

Resolves a peer's id to the sentence a held row speaks with.

readOnly

boolean

default: false

renderIconCircle

(row: WaypointListRow) => ReactNode

required

Draws the disk of one row.

Called for a row when that row renders, and a row renders when its own facts change or when the reference of a prop the list hands every row does, this slot's among them. It is not called at each render of the list. So a slot that reads a value outside its arguments changes identity with that value, as a useCallback that lists it does: a slot whose reference stands keeps what it drew.

renderIndicators

(waypointId: string) => ReactNode

Host badges for one row, such as who is looking at the place.

Called when renderIconCircle is, under the same rule: a slot that reads a value outside its argument changes identity with that value.

renderMenuItems

(row: WaypointListRow) => ReactNode

Host menu items for one row, above its own verbs.

Per row rather than one node, for the reason renderIconCircle is: an item acting on a place has to know which place. A draft row is passed too: a host offering an action a waypoint cannot answer until it is saved decides that itself, from row.isDraft.

Called when renderIconCircle is, under the same rule: a slot that reads a value outside its argument changes identity with that value.

itineraryId

string

required

The itinerary whose waypoints the list renders.

waypoints

ItineraryViewSource["waypoints"]

required

The SAVED waypoints, in position order.

EditorListSection

action

ReactNode

children

ReactNode

required
count

number

required
label

string

required
limit

number

limitTooltip

string

required

boolean

SegmentSeam

afterSegmentId

string | null

required
controlsEnabled

boolean

required
group

SegmentSeamGroup | null

required
groupChipDisabledHint

string | null

required
insertEngineChoice

boolean

required
insertMode

SegmentEditMode | null

required
merge

SegmentChainMerge | null

required

RadioOptionCard

checked

boolean

required
description

string

disabled

boolean

glyph

UiGlyph

media

ReactNode

specs

ReactNode

title

string

required
value

string

required

StudioToggleRow

checked

boolean

required
disabled

boolean

glyph

ReactNode

label

string

required

PrivacyControl

caption

ReactNode

disabled

boolean

resource

"collection" | "itinerary" | "zone"

required
value

boolean

required

LanguageSelect

aria-label

string

description

string

disabled

boolean

label

string

options

readonly { label: string; value: MapLanguage }[]

required
renderMark

(language: MapLanguage) => ReactNode

value

MapLanguage

required

AllowlistField

label

string

required
description

string

value

string[]

required
data

ComboboxData

required
variant

AllowlistVariant

required
modeLabels

{ all: string; none?: string | undefined; specific: string }

required
placeholder

string

nothingFoundMessage

string

disabled

boolean

readOnly

boolean

error

ReactNode

Why the list was refused, shown under the picker, which it marks invalid and describes. A refusal answered at an entry of the list (an entry the catalogue no longer holds) belongs here, beside the entry the reader removes, rather than in a toast. Left out, the field shows none.

OrganizationScopeOptionRow

name

string

required
membershipRole

OrganizationRole | null

required

AgentThreadsProvider

children

ReactNode

required

The tree that reads the threads: every surface that shows or drives a conversation.

enabled

boolean

default: true

Whether the co-pilot runs here. A provider that is not enabled builds no engine, opens no transport and registers no tab strip: its readers see a conversation set that stays empty on the Search tab, and its commands do nothing, so the co-pilot's panel never opens. The tree beneath keeps its place across a change of it.

invalidateAiConfig

(organizationId: string) => void

invalidateAiConfig marks the organization's AI configuration stale after a fault that turns on it: a run refused as not-configured, or one refused for access.

A callback rather than a query key read here, because the key belongs to whatever cache the host binds and this provider has no business naming one: the conversation faults it feeds already take the invalidation as a function. Absent, the fault still surfaces its message and the config is re-read on the next natural refetch, which is the correct defined absence for a host with no cache of its own.

invalidateMemberships

() => void

invalidateMemberships marks the reader's memberships stale after a run is refused or ended for want of access: its start or its stream answered 402, 403 or 404, a message that found its run gone, or a run ended because its member may not run it there any more (no write role in its organization, or an agreement that does not include Map Studio).

A callback for the reason {@link invalidateAiConfig} is one: the memberships are whatever the host's cache holds. The co-pilot's availability is read off them, so the notice that follows the refresh says why the co-pilot is withheld. Absent, the refusal still surfaces its message and the memberships are re-read on their next refetch.

recoveryAddendum

RecoveryAddendum

The host's own remedy for a failed call, appended to the playbook's recovery the model reads with it; see {@link RecoveryAddendum}. Omitted, the model reads the playbook's recovery alone.

routesServerTools

boolean

Whether a run names the server tools its model sees, from the tools the conversation's surfaces route to. Leave it off under a publishable key, whose runs call no server tool and are refused a list naming any; turn it on under the browser's own session to narrow the server tools a run offers its model.

threadsUrl

AgentThreadsUrlSeam

How the co-pilot's open conversations survive a reload; see {@link AgentThreadsUrlSeam}.

FullscreenModal

ariaLabel

string

required
children

ReactNode

required

FullscreenHeader

children

ReactNode

closeLabel

string

required
subject

ReactNode

title

string

required

PublicationNotice

itineraryId

string

required
organizationId

string | null

The itinerary's owning organization, which decides whether the reader is offered the act.

The FACT, not the conclusion, as {@link UnpublishedPanel } takes it: the notice asks whether the reader may edit the itinerary itself. Omitted (or the empty string a surface yields mid-read) is no answer yet, and the notice offers publishing: an unanswered question is not a refusal.

state

Extract<PublicationState, "dirty" | "unpublished">

required

UnpublishedPanel

itineraryId

string

required
organizationId

string | null

The itinerary's owning organization, which decides whether publishing is offered at all.

The FACT, not the conclusion: the panel asks usePublishableScope itself rather than taking a canPublish boolean, exactly as ItineraryActionsMenu takes organizationId rather than canEmbed. A host passing the conclusion would be a second place the rule lives, and a host that got it wrong would be silently trusted.

Null is an answer: a personal itinerary names no organization, and the panel states the rule in the act's place. Omitted (or the empty string a surface yields mid-read) is no answer yet, and the panel offers publishing: an unanswered question is not a refusal, and it is also the right default for a host that states no owner at all.

AppModal

children

ReactNode

required
closeLabel

string

required

The close button's accessible name: the localized "Close", on every dialog, so a reader navigating by name meets one target wherever they are. Never a different dismissal's word: a confirm whose X announces "Cancel" beside a footer Cancel is two indistinguishable buttons.

Required rather than resolved here, which is the same contract every other surface in this package keeps: copy arrives from the host, through useMountayaStrings or through a prop.

closeOnClickOutside

boolean

Whether a click on the overlay closes the dialog. A shown-once dialog sets false.

closeOnEscape

boolean

Whether Escape closes the dialog. A shown-once dialog sets false.

description

ReactNode | null

required

The line under the title: either a one-sentence description of the dialog, or the identity of the single named resource it acts on. Required: a dialog that states only a verb leaves the reader to infer what it will act on, and one that drops the line between phases moves everything under it.

Pass null to render without one, which a confirm does: its body IS that sentence, and repeating it in the header would say the same thing twice. Required-with-an-explicit-null rather than optional, so leaving it out is a compile error instead of a silent omission.

footer

ReactNode

The action row pinned below the body, usually a {@link ModalFooter }.

icon

ReactNode

The glyph for the leading icon accent, framed in a light ThemeIcon.

iconColor

string

The accent the header glyph is tinted with: a design-system colour name or a CSS colour.

A string rather than a tone, and rather than Mantine's own MantineColor. This shell is generic: it carries a product's own identity colour as readily as a caution, and a closed set of three would make the first unexpressible, and Mantine's colour type would make the second a design system's name.

{@link ConfirmModal } is the surface that does take a closed set (see its tone), because a confirmation has three meanings and no more.

keepMounted

boolean

Keeps the body mounted while closed (Mantine's keepMounted), for a dialog whose body holds state that must survive a reopen.

opened

boolean

required
size

StudioSize | (string & {}) | number

default: "md"

The dialog's width: "md" is the form width, and a confirm or simple dialog passes "sm".

title

string

required

The dialog heading, and its accessible name. A STRING, not a node: it renders inside the <h2> the dialog's aria-labelledby points at, where a node would both nest flow content in a heading and read out as part of the announced name. Anything richer belongs on description, which is a sibling of the heading for exactly that reason.

titleHidden

boolean

default: false

Whether the title is drawn for assistive technology alone: it names the dialog all the same, and no eye meets it. For a dialog whose body opens on a heading of its own that says the same, so the name is not shown twice. The header then holds the close button alone, with no divider under it.

withCloseButton

boolean

default: true

Whether the header shows its close button. A shown-once reveal phase hides it.

zIndex

number

ModalFooter

cancelLabel

string

The abandon button's label; pairs with onCancel to render a Cancel.

Required in practice ALONGSIDE confirmLabel and meaningless without it: a Cancel is what the confirm is abandoned in favor of, so a row offering only a way out is a dismissal wearing a button. The pairing is the call site's to keep rather than a type's, which a never union could only make harder to read.

confirmColor

StudioTone

The confirm's tone: danger for a destructive confirm, primary for an affirmative one.

confirmDisabled

boolean

Disables the confirm, for a confirm gated on a precondition the dialog shows itself.

confirmDisabledReason

string

Disables the confirm and says why: in a tooltip under it, and in a polite live region for assistive technology. The host's own words.

confirmLabel

string

The primary action's label, and the reason the row exists.

OPTIONAL, for the one shape that has no primary: a dialog whose only offer is the side action in secondary (copy a revealed key, disable a share link). A "Done" beside it is the corner X spelled as a button: two dismissals, one of them dressed as the primary action. Without it the real action stands alone in the row and the X is the single way out.

Never a dismissal's word. A footer reading "Close", "Done" or "OK" is a dialog with nothing to do, and that dialog takes NO footer at all: the X already closes it.

mt

StudioSpace

Extra top margin on the action row, opening space between it and the body.

pending

boolean

Whether the confirmed action is out: the confirm spins and Cancel is disabled, so the action is neither fired twice nor dismissed from under itself.

secondary

ReactNode

A non-cancel secondary action pinned to the row's far left, opposite the confirm.

ConfirmModal

acknowledgeLabel

string

The label of an "I understand…" checkbox below the body that gates the confirm button, for the highest-stakes deletes, where a stray click would destroy a whole resource. Confirm stays disabled until it is ticked, and the tick resets each time the dialog opens.

body

ReactNode

required

The consequence the reader confirms: a string renders as a paragraph, a node as it is.

cancelLabel

string

required

The footer's dismissal, which keeps things as they are ("Cancel", "Keep editing").

closeLabel

string

required

The header close button's accessible name: the localized "Close". It is distinct from cancelLabel even though both dismiss: two buttons in one dialog that announce themselves identically are indistinguishable to anyone navigating by name.

confirmLabel

string

required

The footer's confirm, named by its verb ("Delete itinerary").

icon

ReactNode

Overrides the leading header glyph.

loading

boolean

default: false

Whether the confirmed action is out: Confirm shows its spinner, and every way out (Cancel, the close button, Escape and the overlay) is held until it settles.

opened

boolean

required

Whether the dialog shows. The caller owns it.

title

string

required

The dialog's heading and accessible name, in sentence case ("Delete itinerary").

tone

ConfirmationTone

default: "destructive"

How loud the prompt is. destructive is the default because it is the safe direction to be wrong in: this dialog exists for consequential verbs, so the loudest treatment is the default and a softer one is an explicit opt-in.

The BUS's own vocabulary, and that is the point of taking it rather than two colour props. A tool declares a tone on its confirm policy, useConfirmGate hands it straight through, and nothing between the two has to know what red is.

zIndex

number

The dialog's stacking order, for a confirm raised over a surface that sets its own, such as the full-screen scrim of an agent-driving overlay, so the confirm stays clickable on top.

SidenavContentHeader

backDisabled

boolean

backDisabledLabel

string

backLabel

string

icon

undefined

actions

ReactNode

description

string

subtitle

ReactNode

title

ReactNode

required

SidenavContentBody

children

ReactNode

required

SidenavFormActions

banner

ReactNode

hint

ReactNode

primaryDisabled

boolean

primaryDisabledReason

string

primaryLabel

string

required
primaryLoading

boolean

secondary

ReactNode

The flow's lesser verbs, on the button's row before it.

ErrorAlert

children

ReactNode

required
title

string

ListSkeleton

height

number

default: 44

Each stripe's height, in pixels: a list row's resting height, so the skeleton holds the space the rows will.

rows

number

default: 3

How many stripes to draw.

EmptyState

action

ReactNode

description

string

icon

ReactNode

required
size

EmptyStateSize

default: "md"

title

string

required

WarningAlert

children

ReactNode

required
title

string

FormErrorAlert

message

string | null

required

ActivityIcon

glyphSize

string

label

string

size

string

default: "1.75rem"

slug

RestActivitySlug

required

DialogSubject

ascent

string

default: ""

distance

string

default: ""

name

string

required
qualifier

string

slug

RestActivitySlug | null

ItineraryActionsMenu

createdById

string

The id of the user who created the itinerary, its own created_by.id. With organizationId it decides whether the reader may change the itinerary: a personal itinerary is its author's alone. Omitted, no author is known, and under a roster the host states a personal itinerary offers no item that changes it.

editItem

ReactNode

The item that opens the editor, which only a host can build: it is a LINK to their own route, and it has to behave like one (a modifier-click opens a tab, a right-click offers the address). A <Menu.Item component={Link}> from their router goes here.

Omitted, the item is not rendered, which is also what a host already INSIDE the editor wants: there is nowhere left to navigate. It is left out for a reader who may not edit the itinerary, as Rename is.

itineraryId

string

required

The itinerary every item acts on.

organizationId

string

The id of the organization that owns the itinerary, its own organization_id, which gates every output of the menu. Every host passes the itinerary's own, so the gate runs against the real owner rather than a workspace fallback, a foreign itinerary opened by a direct link included. Omitted, with no owner known, every output is withheld.

position

FloatingPosition

default: "bottom-end"

Where the dropdown opens. A host anchored to the bottom of the viewport (the elevation panel) passes a "top-*" position, and the menu then opens upward and stays up rather than flipping back down. The item order is the same either way: Delete stays last.

published

boolean

default: false

Whether the itinerary has a publication, which puts the Unpublish item in the menu for a reader who holds the write grant. The host answers it because the host holds the record (the sidenav row has the listing's status, the detail panel the open itinerary's). Omitted, by a surface that cannot answer, the item is not rendered rather than offered against an unknown state. It sits in its own band above Delete: the two are the ways an itinerary stops being available, and the divider between them says only one of the two is permanent.

segmentCount

number

required

How many segments the itinerary holds. With none, every output that reads the geometry is disabled with its reason.

triggerVisible

boolean

default: true

Whether the trigger shows. The host turns it on while its row is hovered or focused, and an open menu always shows its trigger.

ItineraryForm

draftFlow

DraftEditorFlow | null

The flow whose staged draft the form edits while itinerary is null: its metadata is read off the draft's session and written through the flow's setters, and Create commits the draft. Omitted or null, with no itinerary, the form is the manual create, whose submit creates an itinerary shell and arms its first segment.

itinerary

ItineraryWithDetails | null

required

The open itinerary, which the form edits: the activity is locked and the name renames in place. Collection membership lives in the Manage collections dialog. Null for a create or a staged draft.

strings

ItineraryFormStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

ItineraryProfilePanel

collapsed

boolean

default: false

Shrinks the profile to its characteristics row while a floating panel is open. A height-aware host (the in-app studio and the embed) drives it from the resolved profile visibility.

embedded

boolean

default: false

Whether the panel is drawn in an embed. The in-app studio renders the actions menu beside the segment chooser; an embed renders none, since its download lives in a map control. It also moves the analysis gate from the viewer's profile-insights entitlement to the publisher's showAnalysis.

segmentColor

string

One colour every band is painted in, in place of each segment's own, so the chart matches an embed's single-colour map. Omitted, each band keeps its segment's colour.

showAnalysis

boolean

default: true

Whether the analysis section (the surface and way-type bars) renders.

showCharacteristics

boolean

default: true

Whether the characteristics row renders.

showElevation

boolean

default: true

Whether the elevation chart renders.

showPaceControl

boolean

default: false

Offers the reader their own travel pace, re-timing the profile's figures for their session alone. The surfaces that publish an itinerary to somebody else (the embed and the share view) pass it; the authenticated studio has a rate field per segment.

surface

ItinerarySurface

The snapshot the pace re-time is asked for. A preview that authenticates as the owner passes "published", so the reader's pace re-times the route a visitor is served rather than the draft. Omitted, the credential decides, which is the published copy for a visitor.

PersistedSegmentRow

groupActions

SegmentRowGroupActions

groupRail

SegmentRowGroupRail

insertMode

SegmentRowChainOptions["insertMode"]

The engine an insert beside the row opens in, for an activity that offers one engine alone. Null for an activity no engine serves, whose row offers no insert. Omitted, an insert opens in the segment's own engine.

isCommitted

boolean

required
itineraryId

string

required
mergeNextDisabledReason

SegmentMergeDisabledReason | null

required
mergePreviousDisabledReason

SegmentMergeDisabledReason | null

required
previousSegmentId

string | null

required
segment

ItinerarySegment

required
splitDisabledReason

SegmentSplitDisabledReason | null

required
activityDefaultSpeed

number | null

required
activitySlug

string | null

required
isFirst

boolean

required
isLast

boolean

required

DraftSegmentRow

isOnly

boolean

required
liveSegment

ItinerarySegment | null

previousEnd

[number, number] | null

required
segment

ItineraryDraftSegment

required
strings

DraftSegmentRowStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

activityDefaultSpeed

number | null

required
activitySlug

string | null

required
isFirst

boolean

required
isLast

boolean

required

ItineraryHeaderTitle

name

string

required
rename

InlineRename

required
strings

ItineraryHeaderTitleStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

EditorSaveFooter

client

MapClient | null

required

The live map client, the segment family's draft source: a segment's handles live on the canvas, not in the store. The waypoint family ignores it.

itineraryId

string | null

required

The itinerary every save is sent for, or null over a staged draft, whose saves the studio writes into the draft.

strings

EditorSaveFooterStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

StagingCreateFooter

draftFlow

DraftEditorFlow

required

The flow whose staged draft the Create action commits.

strings

StagingCreateFooterStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

WaypointIconCircle

color

string | null

required
colorless

boolean

default: false

disabled

boolean

default: false

icon

WaypointIcon | null

required
itineraryId

string

label

string

required
session

boolean

default: false

waypointId

string

required

DraftProvenanceBanner

draftFlow

DraftEditorFlow

required

The staging flow that seeded the unsaved draft: a suggested route or an imported file. It is the flow the panel is in, as the studio's DraftEditorFlow names it.

strings

DraftProvenanceBannerStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

ZoneActionsMenu

createdById

string

The id of the user who created the zone, its own created_by.id. With organizationId it decides whether the reader may reshape, withdraw or delete the zone: a personal zone is its author's alone. Omitted, no author is known, and under a roster the host states a personal zone offers none of the three.

level

ZoneEditLevel

required

The zone's severity, which a reshape by hand opens its edit in.

mode

ZoneEditMode

required

The zone's shape, which a reshape by hand opens its edit in.

organizationId

string | null

The organization the zone belongs to, or null for one kept in the personal space: the scope the host's writeRefusal is asked about, so a zone whose scope takes no edit offers Reshape by hand disabled, with the reason, and with createdById the owner the reader's write grant is read against. Omitted, no scope refuses Reshape by hand and the verb answers for itself.

published

boolean

default: false

Whether the zone has a publication, which puts the Unpublish item in the menu for a reader who holds the write grant. The host answers it because the host holds the record (the panel has the bound zone's status). Omitted, by a surface that cannot answer, the item is not rendered rather than offered against an unknown state. It sits in its own band above Delete: the two are the ways a zone stops being available, and the divider between them says only one of the two is permanent.

sourced

boolean

required

Whether the zone is computed from a stored query, the one kind Reshape by hand is offered for, to a reader who holds the write grant.

zoneId

string

required

The saved zone the menu acts on.

strings

ZoneActionsMenuStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

StudioSectionBoundary

children

ReactNode

required

The surface a render error is contained to.

StudioPortalScope

children

ReactNode

The studio's own content: every surface inside it portals into this scope's node.

EmbedWizard

useKeys

StudioEmbedKeysSeam

The hook that answers the publishable keys an embed of the resolved organization may carry.

The wizard calls it as a hook, on every render, so it keeps one identity for the wizard's life: a hook declared at module scope, as {@link EmbedWizard}'s example hands one. Handing another hook, or none, to an open wizard changes the hooks it calls.

useOrganization

StudioEmbedOrganizationSeam

The hook that answers what the host can say about the organization the resource belongs to. It keeps one identity for the wizard's life, as {@link useKeys} does.

target

ShareLinkTarget

required

The itinerary or the collection the snippet is authored for, as { kind, id }: the target studio.embed.open takes and the embed slot holds.

strings

EmbedWizardStrings

Overrides the words this surface says, for this surface only.

Folded onto whatever the provider resolved, so an override naming one key leaves the rest of the section alone, and carried down to the rows and pickers this surface mounts. Scoped to the sections it renders: a key it never says is a type error rather than a silent no-op.

EmbedFieldControl

config

EmbedConfig

required
field

EmbedConfigField

required
layerOptions

EmbedLayerOptions

required
safetyRules

EmbedSafetyRules | undefined

required

ImportRoutingGuideProvider

children

ReactNode

required
pictures

ImportRoutingGuidePictures

The pictures the guide's two comparisons are drawn from, each as a URL the host serves. The package ships none, so a host that supplies none gets both arguments in words.

Handlers

An on* handler suppresses the element's own default. Left unset, the element acts; set, it becomes presentational and your handler decides. The two never both fire.

SegmentList

onExplainEngines

() => void

onExport

(segmentId: string) => void

Downloads a segment, called with its id, which the published rows offer as Download segment once the chain carries them. Omitted, no row offers a download. Downloading is a Map Publishing act, which the viewer's publish entitlement answers: a host passes it to a viewer holding publish.

onFailure

(failure: SegmentRowFailure) => void

A refusal from one of the list's chain verbs or group verbs, in the row's own vocabulary.

SegmentRowFailure rather than a union of the list's own, because a host maps every refusal to a sentence in ONE place: a gutter's insert and a row menu's insert are the same refusal reaching the user from two controls, and giving them two vocabularies would make the host answer the same question twice and eventually differently.

For the same reason it hears the refusals a row keeps as its lastFailure and no others: a withheld confirmation ({@link isConfirmationWithheld}) never reaches it, since the verb never ran.

WaypointList

onOpen

(row: WaypointListRow) => void

What a single click on a row's body opens, replacing the move session it otherwise starts.

Per row for the reason renderMenuItems is: whatever it opens has to know which place. A surface that leaves it out keeps the move, which is what a list with no dialog behind it should do.

onFailure

(failure: WaypointRowFailure) => void

A refused verb of a row, handed to the host to report where it belongs on their surface.

SegmentSeam

onEditGroup

(groupId: string) => void

required
onInsert

(afterSegmentId: string | null, mode: SegmentEditMode) => void

required
onMerge

(segmentId: string) => void

required
onMergePreview

(segmentIds: readonly string[] | null) => void

required

StudioToggleRow

onToggle

(enabled: boolean) => void

required

PrivacyControl

onChange

(isPrivate: boolean) => void

required

LanguageSelect

onChange

(language: MapLanguage) => void

required

AllowlistField

onChange

(next: string[]) => void

AgentThreadsProvider

onSignInRefused

() => void

onSignInRefused asks the host whether the reader is still signed in after the API refused the browser's own session under a run: its start, its stream or a message into it answered 401, as it is once the reader signs out or their session is revoked. Called once per refusal.

A callback for the reason {@link invalidateAiConfig} is one: how a person signs in is the host's. It is handed to the engine only where the client above rides the browser's own session: under a publishable key a 401 refuses the key or the session token beside it, which is no sign-in a host can ask about. Absent, the refusal still surfaces its message.

FullscreenModal

onClose

() => void

required

FullscreenHeader

onClose

() => void

required

AppModal

onClose

() => void

required
onSubmit

FormEventHandler<HTMLFormElement>

Renders the body AND the footer as one <form> with this submit handler, so a footer whose confirm omits onConfirm submits it. Without this the footer is a sibling of the body and a form-backed dialog would have to smuggle its action row into children to keep the submit button inside the form.

ModalFooter

onCancel

() => void

Abandon handler the Cancel button calls; pairs with cancelLabel.

onConfirm

() => void

Called by the confirm.

ConfirmModal

onCancel

() => void

required

Called by every dismissal: Cancel, the close button, Escape and the overlay.

onConfirm

() => void

required

Called by Confirm.

SidenavContentHeader

onBack

() => void

SidenavFormActions

onPrimary

() => void

required

ItineraryActionsMenu

onToggle

(opened: boolean) => void

Told the menu's open state at each change of it: true as the reader opens the menu and false as it closes, whichever way it closes. A parent holds its own surface visible while the menu is open through it (the sidenav row pins its data-menu-open highlight this way).

A co-pilot run that starts while the menu is open closes it, and that close is reported as false like any other, so a host that mirrors the state holds nothing open through the run and the menu does not open by itself as the run ends.

onRename

() => void

The host's rename entry point. Present, the menu shows a Rename item that calls it, to a reader who may edit the itinerary; omitted (a host with no inline rename, such as the elevation panel), the item is not rendered.

PersistedSegmentRow

onExport

SegmentRowProps["onExport"]

Downloads a segment, called with this row's id, which puts Download segment in a committed row's menu. It is the published row's own onExport, handed down unchanged: the list that holds the viewer passes it to a viewer holding publish, and a row given none offers no download.

EmbedFieldControl

onPatch

(patch: EmbedConfigPatch) => void

required