Coordinate Input
Latitude and longitude, accepting decimal degrees or DMS. A latitude above 90 is reported as "is this a longitude?" rather than "out of range" — swapped pairs are the most common coordinate bug there is.
src/components/ui/coordinate-input.tsxAbout
From the component's own source, where it was written.
Latitude and longitude, accepting decimal degrees or DMS.
People paste coordinates from wherever they found them — 51.5074, -0.1278 from a URL, 51°30'26.6"N 0°07'39.9"W from a chart. Rejecting the second form means the user converts it by hand, which is exactly where a digit gets dropped. Both are parsed; the canonical decimal pair is what leaves.
A single field accepts a pasted pair and splits it, because a comma-separated pair is how coordinates travel and forcing two paste operations is a small cruelty.
Ranges are checked and, more usefully, so is the *ordering*: a latitude above 90 is almost always a longitude in the wrong box. Saying so is more helpful than "out of range", and swapped pairs are the most common coordinate bug there is.
Six decimal places is the display precision — about 11cm. More digits imply an accuracy no consumer GPS has.
Install
npx astralyx-ui add coordinate-input
Usage
import { CoordinateInput } from '@/components/ui/coordinate-input'
<CoordinateInput value={value} onValueChange={setValue} />Composer
Change the props and the source below follows.
<CoordinateInput value={value} onValueChange={setValue} />Examples
Round-tripping a pair
const [value, setValue] = useState({ lat: 51.5074, lng: -0.1278 })
<CoordinateInput value={value} onValueChange={setValue} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
CoordinateInput
Extends Omit<ComponentProps<'div'>, 'onChange' | 'value'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | Coordinate | null | — | { lat, lng }. null while the fields do not parse to a valid pair. |
| onValueChange | (value: Coordinate | null) => void | — | — |
| size | 'sm' | 'md' | 'md' | — |
| disabled | boolean | — | — |
| copyable | boolean | true | — |
| latitudeLabel | ReactNode | 'Latitude' | — |
| longitudeLabel | ReactNode | 'Longitude' | — |
| latitudePlaceholder | string | '51.5074' | — |
| longitudePlaceholder | string | '-0.1278' | — |
| copyLabel | string | 'Copy coordinates' | — |
| invalidNote | ReactNode | 'Not a coordinate' | Shown when a field does not parse at all. |
| latitudeRangeNote | ReactNode | 'Above 90° — is this a longitude?' | Shown for a latitude past ±90 — usually a swapped pair. |
| longitudeRangeNote | ReactNode | 'Beyond 180°' | — |
Functions
| Function | Signature | Description |
|---|---|---|
| parseCoordinate | (raw: string) => number | null | Decimal degrees, or degrees/minutes/seconds with an optional hemisphere. |
| parseCoordinatePair | (raw: string) => Coordinate | null | Splits a pasted lat, lng pair on a comma or whitespace between the two. |
Types
Coordinate
Latitude and longitude, accepting decimal degrees or DMS.
| Field | Type | Description |
|---|---|---|
| lat | number | — |
| lng | number | — |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| input formats | decimal or DMS | Both 51.5074 and 51°30'26.6"N parse. Rejecting the second means the user converts by hand, which is where a digit gets dropped. |
| paste | splits a pair | Pasting 51.5074, -0.1278 into either field fills both — a comma-separated pair is how coordinates travel. |
| precision | 6 places | About 11cm. More digits imply an accuracy no consumer GPS has. |