# Area select
> Draw a rectangle of latitude and longitude on a map to select an area, for example to filter events by place.
- React: `import { GeoArea } from "@/components/lumesec/geo-area"`
- Collection: Location (https://elements.lumesec.ai/components/location)
- Data: takes your data (`data`); shows demo data until you pass it
- Registry item: https://elements.lumesec.ai/r/geo-area.json
- Page: https://elements.lumesec.ai/components/location/area



Live preview: https://elements.lumesec.ai/view/geo-area

Demo source:

```tsx
"use client";

import * as React from "react";

import { formatArea, GeoArea, type GeoBounds } from "@/components/lumesec/geo-area";

/** Western and central Europe. */
const EUROPE: GeoBounds = { west: -12, south: 35, east: 30, north: 60 };
/** From 140° E across the date line to 170° W: `east` past 180 continues on the other side of the map. */
const PACIFIC: GeoBounds = { west: 140, south: -20, east: 190, north: 25 };

const BUTTON =
  "h-[30px] cursor-pointer rounded-lg border border-border bg-card px-[11px] font-[inherit] text-[12.5px] font-medium text-foreground outline-none hover:border-[color-mix(in_srgb,var(--lumesec)_50%,var(--border))] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-lumesec";

export default function GeoAreaDemo() {
  const [area, setArea] = React.useState<GeoBounds | null>(EUROPE);

  return (
    <div className="grid w-full max-w-[660px] gap-3">
      <GeoArea value={area} onValueChange={setArea} label="Event area" />
      <div className="flex flex-wrap items-center gap-2">
        <button type="button" className={BUTTON} onClick={() => setArea(EUROPE)}>
          Europe
        </button>
        <button type="button" className={BUTTON} onClick={() => setArea(PACIFIC)}>
          Across the date line
        </button>
        <span className="ml-auto text-[12px] text-muted-foreground">Demo data</span>
      </div>
      <p className="m-0 min-w-0 truncate text-[12.5px] leading-5 text-muted-foreground">
        Committed:{" "}
        <span className="font-mono text-foreground tabular-nums">{area ? formatArea(area) : "no area"}</span>
      </p>
    </div>
  );
}
```

## Installation

```bash
npx shadcn@latest add @lumesec/geo-area
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/geo-area.json
```

## Usage

React:

```tsx
import { GeoArea, type AreaPoint, type GeoBounds } from "@/components/lumesec/geo-area";

const events: AreaPoint[] = [
  { lat: 48.86, lon: 2.35 },
  { lat: 52.52, lon: 13.4 },
  { lat: 40.71, lon: -74.01 },
];

export function Example() {
  return (
    <GeoArea
      points={events}
      defaultValue={{ west: -12, south: 35, east: 30, north: 60 }}
      onValueChange={(area: GeoBounds | null) => console.log(area)}
    />
  );
}
```

## Behaviour

Draw a rectangle of latitude and longitude on a map to select an area, for example to filter events by place. Move it, resize it from its edges and corners, type exact bounds, or double-click a country to fit the box to it.

While you draw, the land inside fills behind the pointer with a bright, uneven front, the dotted border runs, and the count of points inside rolls. On release the edges snap to whole degrees on springs. The box can cross the date line and continue on the other side of the map.

## API reference

### Ref

`ref` points at the root `HTMLDivElement`.

## Theming

Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).


