# MapViewControl

## Overview

`MapViewControl` switches between named map views and exposes the reframe action. It is presentational: it reports the user's choice, and `<Map>` moves the camera. Hand the same `views` / `activeViewId` / `onViewChange` triple to both components.

---

## Import

```tsx
import { MapViewControl, type MapView } from 'xertica-ui/ui';
```

---

## Prerequisites

- Import `xertica-ui/style.css` once at the app root.
- For `variant="overlay"`, wrap the map and the control in a container with `position: relative`.
- The `views` array and `activeViewId` must be the same values passed to `<Map>`.

---

## Props

| Prop           | Type                    | Default             | Description                                                  |
| -------------- | ----------------------- | ------------------- | ------------------------------------------------------------ |
| `views`        | `MapView[]`             | required            | Named camera positions.                                      |
| `activeViewId` | `string`                | -                   | Id of the active entry.                                      |
| `onViewChange` | `(id: string) => void`  | required            | Called with the chosen view id.                              |
| `onRefit`      | `() => void`            | -                   | Reframes around current data. The button hides when omitted. |
| `refitLabel`   | `string`                | `"Reframe to data"` | Accessible name and tooltip for the reframe button.          |
| `variant`      | `'inline' \| 'overlay'` | `'inline'`          | `overlay` floats over the map.                               |
| `position`     | `MapOverlayPosition`    | `'top-left'`        | Anchor for `variant="overlay"`.                              |
| `ariaLabel`    | `string`                | `"Map views"`       | Accessible name for the control group.                       |

### `MapView`

| Field    | Type                                       | Description                                     |
| -------- | ------------------------------------------ | ----------------------------------------------- |
| `id`     | `string`                                   | Required, stable.                               |
| `label`  | `string`                                   | Button text.                                    |
| `center` | `LatLng`                                   | Camera center. Use with `zoom`.                 |
| `zoom`   | `number`                                   | Camera zoom.                                    |
| `bounds` | `LatLng[] \| { north, south, east, west }` | Frame instead of center/zoom. Takes precedence. |

---

## Example

```tsx
import { Map, MapViewControl, type MapView } from 'xertica-ui/ui';

const views: MapView[] = [
  { id: 'estado', label: 'Estado', center: { lat: -30.0, lng: -52.5 }, zoom: 6 },
  { id: 'metro', label: 'Região metropolitana', center: { lat: -29.98, lng: -51.15 }, zoom: 10 },
];

function Panel() {
  const [activeViewId, setActiveViewId] = useState<string | undefined>('estado');

  return (
    <div className="relative">
      <Map
        height="480px"
        fitTo="markers"
        views={views}
        activeViewId={activeViewId}
        markers={markers}
      />
      <MapViewControl
        variant="overlay"
        position="top-left"
        views={views}
        activeViewId={activeViewId}
        onViewChange={setActiveViewId}
        onRefit={() => setActiveViewId(undefined)}
      />
    </div>
  );
}
```

Clearing `activeViewId` hands control back to `fitTo`, which is why the reframe action above sets it to `undefined`.

---

## AI Rules

- **Always** pass the same `views` and `activeViewId` to `<Map>` and to `<MapViewControl>`. Different values make the buttons lie about where the camera is.
- **Always** wrap the map and the control in a `relative` container when using `variant="overlay"`.
- **Never** pass a no-op to `onRefit` — omit it, and the button hides itself.
- **Never** expect `fitTo` to re-frame while `activeViewId` is set. An explicit user choice outranks automatic fitting; clear the id to restore it.
- Common mistake: rebuilding the view switcher with raw `<button>` elements. Use this component so keyboard operation and focus states come from the design system.
