Skip to main content
BrownieJS
Open Source

A biblioteca de mapas React com 9 kB.

Zero dependências. Sem Leaflet, sem Mapbox — só tiles, vetores e controle total.

$npm install @brownie-js/react

Por que BrownieJS?

Zero Dependências

Sem Leaflet, sem Mapbox. TypeScript puro — você controla cada pixel.

Bundle Minúsculo

~9kB gzipped. Mapas interativos sem inflar sua aplicação.

Amplamente Testado

Suite de testes abrangente cobrindo cada componente e hook.

Acessível

Navegação por teclado, labels ARIA, indicadores de foco. Conforme WCAG 2.1 AA.

Veja em ação

Mapa Interativo com Tiles

Tiles OpenStreetMap com marcadores, clusters, popups e círculos geográficos. Arraste e amplie para explorar.

import { useState } from 'react';
import { GeoMap, TileLayer, Marker, Popup, Circle, MapControl } from '@brownie-js/react';
import { MarkerCluster } from '@brownie-js/react/cluster';
import { ZoomControl, ScaleBar } from '@brownie-js/react/controls';

const animals = [
  { id: '1', name: 'Rex',  type: 'lost',  coordinates: [-46.65, -23.56] },
  { id: '2', name: 'Luna', type: 'found', coordinates: [-46.63, -23.55] },
  { id: '3', name: 'Max',  type: 'lost',  coordinates: [-46.64, -23.54] },
  { id: '4', name: 'Mel',  type: 'found', coordinates: [-46.62, -23.57] },
  { id: '5', name: 'Bob',  type: 'lost',  coordinates: [-46.66, -23.53] },
  { id: '6', name: 'Nina', type: 'found', coordinates: [-46.70, -23.50] },
  { id: '7', name: 'Thor', type: 'lost',  coordinates: [-46.58, -23.60] },
];

const lostColor = '#d4850c';
const foundColor = '#7c8b6f';

function PetFinderMap() {
  const [selected, setSelected] = useState(null);
  const animal = animals.find((a) => a.id === selected);

  return (
    <GeoMap center={[-46.63, -23.55]} zoom={13} mapLabel="Pet finder map">
      <TileLayer />
      <Circle center={[-46.63, -23.55]} radius={2000} color="#7c8b6f" />
      <MarkerCluster
        animated
        categoryKey="type"
        categoryColors={{ lost: lostColor, found: foundColor }}
      >
        {animals.map((m) => (
          <Marker
            key={m.id}
            coordinates={m.coordinates}
            color={m.type === 'lost' ? lostColor : foundColor}
            animated
            onClick={() => setSelected(m.id)}
          />
        ))}
      </MarkerCluster>
      {animal && (
        <Popup
          coordinates={animal.coordinates}
          onClose={() => setSelected(null)}
          image={{ src: 'https://placedog.net/400/200?random', alt: animal.name }}
        >
          <strong>{animal.name}</strong> — {animal.type}
        </Popup>
      )}
      <MapControl position="top-right">
        <ZoomControl />
      </MapControl>
      <MapControl position="bottom-left">
        <ScaleBar />
      </MapControl>
    </GeoMap>
  );
}

Geolocalização

Detecte a posição do usuário com um marcador pulsante. Inicia simulado — clique no botão para usar sua localização real.

import { GeoMap, TileLayer, MapControl } from '@brownie-js/react';
import { Geolocation } from '@brownie-js/react/geo';
import { ZoomControl, ScaleBar } from '@brownie-js/react/controls';

function LiveLocationMap() {
  return (
    <GeoMap center={[-46.63, -23.55]} zoom={13} mapLabel="Location map">
      <TileLayer />
      <Geolocation
        watch={true}
        enableHighAccuracy={true}
        onError={(err) => console.warn(err.message)}
      />
      <MapControl position="top-right">
        <ZoomControl />
      </MapControl>
      <MapControl position="bottom-left">
        <ScaleBar />
      </MapControl>
    </GeoMap>
  );
}

Temas

Personalize todos os componentes com MapThemeProvider. Passe um objeto de tema e todos os marcadores, popups, controles e indicadores de foco se atualizam instantaneamente.

import { GeoMap, TileLayer, Marker, MapControl } from '@brownie-js/react';
import { MapThemeProvider } from '@brownie-js/react/theme';
import { ZoomControl, ScaleBar } from '@brownie-js/react/controls';

function ThemedMap() {
  return (
    <MapThemeProvider
      theme={{
        markerColor: '#d4850c',
        popupBg: '#1a0f0a',
        popupColor: '#f5f0eb',
        popupRadius: '12px',
        controlBg: '#1a0f0a',
        controlColor: '#f5f0eb',
        controlShadow: '0 2px 8px rgba(26,15,10,0.4)',
        focusRing: '0 0 0 3px rgba(212,133,12,0.4)',
      }}
    >
      <GeoMap center={[-46.63, -23.55]} zoom={13} mapLabel="Themed map">
       <TileLayer />
        <Marker coordinates={[-46.65, -23.56]} />
        <Marker coordinates={[-46.63, -23.55]} />
        <Marker coordinates={[-46.66, -23.59]} />
        <MapControl position="top-right">
          <ZoomControl />
        </MapControl>
        <MapControl position="bottom-left">
          <ScaleBar />
        </MapControl>
      </GeoMap>
    </MapThemeProvider>
  );
}

Rotas

Roteamento rodoviário entre pontos usando OSRM. Explore diferentes modos de roteamento.

import { GeoMap, TileLayer, Marker, MapControl } from '@brownie-js/react';
import { Route } from '@brownie-js/react/route';
import { ZoomControl, ScaleBar } from '@brownie-js/react/controls';

function FixedRoute() {
  return (
    <GeoMap center={[-44.9, -23.2]} zoom={7} mapLabel="Route map">
      <TileLayer />
      <Route
        coordinates={[[-46.63, -23.55], [-43.17, -22.91]]}
        color="#d4850c"
        strokeWidth={3}
        routing={true}
        animated
        animationSpeed={2}
        onRouteLoaded={(data) =>
          console.log(`${(data.distance / 1000).toFixed(0)} km`)
        }
      />
      <Marker coordinates={[-46.63, -23.55]} color="#7c8b6f" animated />
      <Marker coordinates={[-43.17, -22.91]} color="#d4850c" animated />
      <MapControl position="top-right">
        <ZoomControl />
      </MapControl>
      <MapControl position="bottom-left">
        <ScaleBar />
      </MapControl>
    </GeoMap>
  );
}
Brownie, a brown Shih Tzu

Por que "Brownie"?

Brownie era um Shih Tzu que chegou ao mundo nas nossas mãos e partiu da mesma forma — cedo demais, com apenas um ano e meio. Ele tinha um coração maior do que seu pequeno corpo podia conter. Esta biblioteca leva o nome dele porque todo projeto deveria ser construído com a mesma alegria que ele trazia a tudo que explorava. Mapas nos ajudam a encontrar caminhos. O Brownie nos ajudou a encontrar o nosso.

Mapas em 5 linhas de código.

Instale, componha, publique. BrownieJS funciona com qualquer setup React.

$npm install @brownie-js/react