> ## Documentation Index
> Fetch the complete documentation index at: https://help.stralos.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Location picker

> Address search, map selection, and coordinate entry

`@stralos-co-nz/maps-ui` exports the controlled `LocationPicker` component. Use it when a form needs a stored address and coordinates.

## Value and props

`LocationPickerValue` contains `addressLine1`, `latitude`, `longitude`, `city`, `region`, and optional `countryCode`. Coordinates remain strings in form state and confirmed selections are formatted to six decimal places.

| Prop | Default | Purpose |
| - | - | - |
| `value`, `onChange` | Required | Supply and update the controlled location value. |
| `entityLabel` | `location` | Describe the selected entity in map guidance and fallback text. When the label already ends with the word "location" (case-insensitive), the picker uses it verbatim rather than appending " location" again — so passing `"location"` produces "location", not "location location". |
| `countryCodes` | `nz` | Restrict address search results by country. Pass an empty string to search worldwide. |
| `mapDefaultCenter`, `initialZoom` | Component defaults | Set the empty-map view. |
| `addressRequired` | `true` | Whether the address line 1 field is required. Pass `false` when the owning form treats coordinates as sufficient. |
| `mapDisplay` | `"inline"` | `"inline"` keeps the map always visible. `"collapsible"` hides the map and coordinates behind a disclosure toggle, for use in dialogs. |

### Address search

The **Address search** field uses Places Autocomplete (New) to suggest addresses as you type. Results appear in a dropdown panel below the field.

Selecting a result updates the displayed address and coordinates. It also fills the city, region, and country code when the Places API supplies them. The map pans and zooms to the selected address: the viewport fits the result's bounds at a maximum of zoom 13, or centres on the result at zoom 13 when no bounds are available.

The shell passes `VITE_STRALOS_GEOCODE_COUNTRY` into the picker as `countryCodes`; see [Shell geocoding](https://help.stralos.app/internal/frontend-architecture.md#shell-geocoding).

Consumers that set an `initialZoom` to override the empty-map view do not affect the post-pick zoom; the picker applies zoom 13 independently.

## Map display mode

The `mapDisplay` prop controls whether the map, helper text, and coordinate fields appear inline or behind a disclosure toggle.

| Value | Default | Use for |
| - | - | - |
| `"inline"` | Yes | Pages whose subject is the location — workspace `LocationDetailPage`, project settings. The map is always visible. |
| `"collapsible"` | No | Dialogs and forms where location is secondary — the Add/Edit project dialog, rate reference modals, organisation settings. |

With `mapDisplay="collapsible"`, address search and the Address, City, and Region fields are always visible. The map, its helper sentence, and the Latitude/Longitude fields move behind a "Show map and coordinates" disclosure button. The section is unmounted while collapsed, which removes it from the tab order. A valid pin shows a "Pinned at {lat}, {lon}" summary line while the section is collapsed. If the user enters an invalid coordinate, the section opens automatically so the error is never hidden.

### Map and manual entry

Choosing a point on the map updates latitude and longitude at once. From `@stralos-co-nz/maps-ui` 0.9.0, the picker then reverse-geocodes the pin through the Google Geocoder (debounced, latest drop only) and shows "Finding the address for this pin…" meanwhile. A precise street address is preferred; plus codes, countries and regions are never used as the address line. The result fills the address, city, region, and country code, but the pin keeps its own coordinates. From 0.9.1, a result in the configured home country has the country suffix removed, so it reads like an address picked from search.

If Google returns no usable address, or the lookup fails, and the address is still empty, the picker fills it with `Map-selected <noun>` where `<noun>` is the deduplicated location noun (for example `Map-selected location` or `Map-selected project location`). A hand edit or a search pick made while the lookup is running cancels it. A marker appears only when both coordinates are valid and in range.

The address arrives shortly after the coordinates. A form that requires an address, such as the rates location form, should gate its save on both a non-empty address and valid coordinates.

Users can edit the address, latitude, longitude, city, and region fields directly. Invalid coordinates remain in the controlled value for correction, show an inline validation message, and do not move the marker.

## Coordinate validation (`@stralos-co-nz/ui`)

Pure latitude/longitude parsing and validation, available to consumer save paths so invalid coordinates are rejected before persisting.

### `parseCoordinate(raw, kind)`

Returns the finite in-range number, or `null` for blank, non-finite, or out-of-range input. Never coerces blank to `0`.

```typescript theme={null}
import { parseCoordinate } from "@stralos-co-nz/ui";

const lat = parseCoordinate("-41.3", "latitude"); // -41.3
const bad = parseCoordinate("", "latitude");       // null
```

### `validateCoordinate(raw, kind)`

Returns a `CoordinateField` with `value`, `error`, `isInvalid`, and `isBlank`. Blank input is not an error on its own — required-ness is the consumer's call.

### `validateCoordinatePair(latitudeRaw, longitudeRaw)`

Returns `{ valid, latitude, longitude }`. `valid` is `true` only when both fields are present, finite, and in range — use this condition before saving so blank or invalid coordinates never persist as `0,0`.

```typescript theme={null}
import { validateCoordinatePair } from "@stralos-co-nz/ui";

const result = validateCoordinatePair(latRaw, lngRaw);
if (!result.valid) {
  // show inline errors from result.latitude.error / result.longitude.error
}
```

### Ranges

| Kind | Range |
| - | - |
| `latitude` | −90 to 90 |
| `longitude` | −180 to 180 |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.