Location Picker

Pick a place by searching, or by typing coordinates. Both routes stay open: search covers the common case, the fields cover the field site or mooring that no geocoder knows.

src/components/ui/location-picker.tsx

About

From the component's own source, where it was written.

Pick a place by searching for it, or by entering coordinates directly.

Geocoding is the caller's: pass onSearch and it is called with the query. A component library has no business choosing a geocoder for you — they need keys, they have wildly different terms, and several forbid storing results.

Both routes stay open. Search covers the common case; the coordinate fields cover the one search cannot — a field site, a mooring, an address that no geocoder knows. Hiding the fallback behind an "advanced" toggle just means the people who need it cannot find it.

Results are requested on a trailing debounce and stale responses are dropped by sequence number. Typing "Berlin" fires five requests, and without the guard the answer for "Berl" can land last and win.

Install

npx astralyx-ui add location-picker

Usage

import { LocationPicker } from '@/components/ui/location-picker'

<LocationPicker value={value} onValueChange={setValue} onSearch={geocode} />

Composer

Change the props and the source below follows.

51.50800, -0.12800© OpenStreetMap contributorsOpen map
Props
tsx
<LocationPicker value={value} onValueChange={setValue} onSearch={geocode} />

Examples

Search a place list

API

Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.

LocationPicker

Extends Omit<ComponentProps<'div'>, 'onChange' | 'value'>.

PropTypeDefaultDescription
valueCoordinate | null——
onValueChange(value: Coordinate | null, result?: LocationResult) => void——
onSearch(query: string) => Promise<LocationResult[]>—Your geocoder. A component library has no business picking one — they need keys, terms differ wildly, and several forbid storing results.
placeholderstring'Search for a place or address…'—
showMapbooleantrueRenders a MapEmbed preview of the chosen point on the monochrome basemap.
showCoordinatesbooleantrueThe manual fallback. Not hidden behind an "advanced" toggle, because the people who need it are the ones who cannot find it there.
debouncenumber300—
emptyMessageReactNode'No places matched.'—
searchLabelstring'Search for a place'Accessible name for the search field.
clearLabelstring'Clear selected place'—

Types

LocationResult

Pick a place by searching for it, or by entering coordinates directly.

FieldTypeDescription
idstring—
labelReactNode—
detail?ReactNode—
latnumber—
lngnumber—

Behaviour

TopicDetailDescription
stale responsesdroppedRequests are debounced and tagged by sequence, so the answer for "Berl" cannot land last and beat the one for "Berlin".