@datosgeo-atdt/geo-ui
v1.12.2
Published
Librería de componentes reutilizables en React para aplicaciones geoespaciales, que incluye mapas PMTiles, visualización de datos, unión con CSV y estilos temáticos.
Downloads
5,909
Readme
@datosgeo-atdt/geo-ui
Librería de componentes reutilizables en React para aplicaciones geoespaciales. Incluye visualización de mapas con PMTiles, unión con datos tabulares CSV y estilos temáticos (booleano y Jenks).
Novedades en v1.12
Colores personalizados para mapas: Ahora puedes personalizar completamente los colores de tus mapas con las nuevas props color y colorMunicipios.
- Modo Boolean: Define colores para valores verdaderos y falsos
- Modo Jenks: Genera rampas automáticas entre dos colores o especifica colores exactos para cada clase
- Municipios: Colores independientes para drill-down municipal
- Retrocompatible: Si no especificas colores, usa los defaults actuales
Ver ejemplos de colores personalizados
Instalación
npm install @datosgeo-atdt/geo-ui maplibre-gl pmtiles papaparse @mapbox/vector-tile pbfImportante: Las dependencias react y react-dom son peer dependencies (versión 18+).
Inicio Rápido
Importar componentes
import { MapaPMTiles, TotalesDisplay, DataTable } from '@datosgeo-atdt/geo-ui';
import '@datosgeo-atdt/geo-ui/style.css';Ejemplo mínimo
La biblioteca incluye integrada la URL del PMTiles de entidades de México, por lo que no necesitas especificar pmtilesUrl, sourceLayer ni joinGeomKey:
import { MapaPMTiles } from '@datosgeo-atdt/geo-ui';
import '@datosgeo-atdt/geo-ui/style.css';
function App() {
return (
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
field="valor"
mode="boolean"
/>
);
}Componentes
- MapaPMTiles: Mapas vectoriales interactivos con PMTiles
- TotalesDisplay: Visualización de totales y estadísticas
- DataTable: Tablas de datos con carga de CSV
MapaPMTiles
Componente para renderizar mapas vectoriales usando MapLibre GL y PMTiles con soporte para unión de datos CSV y estilos temáticos.
Características
- PMTiles integrado: URL de entidades de México por defecto
- Join CSV: Unión automática de datos tabulares con geometrías
- Estilos temáticos: Modo booleano y clasificación Jenks
- Colores personalizados: Define tus propias paletas (v1.12.1+)
- Drill-down: Click para explorar municipios
- Popup interactivo: Información al pasar el mouse
- TypeScript: Completamente tipado
Guía de Uso
Uso Básico
Con CSV remoto (URL)
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
field="valor"
mode="boolean"
width="100%"
height={600}
/>Con archivo CSV local
import { useState } from 'react';
import { MapaPMTiles } from '@datosgeo-atdt/geo-ui';
function App() {
const [csvFile, setCsvFile] = useState<File | null>(null);
return (
<div>
<input
type="file"
accept=".csv"
onChange={(e) => setCsvFile(e.target.files?.[0] || null)}
/>
{csvFile && (
<MapaPMTiles
csvFile={csvFile}
field="poblacion"
mode="jenks"
jenksK={5}
/>
)}
</div>
);
}Con PMTiles personalizado
<MapaPMTiles
pmtilesUrl="https://example.com/custom.pmtiles"
sourceLayer="mi-capa"
joinGeomKey="ID"
csvUrl="https://example.com/datos.csv"
field="valor"
mode="boolean"
/>Filtrado y Zoom
Mostrar entidades específicas
Usa fitToIds para mostrar solo las entidades seleccionadas y ajustar el mapa automáticamente:
// Mostrar solo Ciudad de México
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
fitToIds="09"
/>
// Mostrar múltiples entidades (CDMX, Edomex y Jalisco)
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
fitToIds={["09", "15", "14"]}
/>Ventajas:
- Filtra automáticamente para mostrar solo las entidades seleccionadas
- Calcula y ajusta el bbox combinado sin animación de zoom
- Carga directo en la vista correcta
Visualización Municipal
Modo municipios básico
Cuando activas showMunicipios={true}:
- La entidad se muestra solo como contorno
- Los municipios dentro de esa entidad se muestran con el relleno temático
// Mostrar municipios de Ciudad de México
// El CSV debe tener cvegeo municipal (5 dígitos: "09002", "09010", etc.)
<MapaPMTiles
csvUrl="https://example.com/datos_municipales.csv"
fitToIds="09"
showMunicipios={true}
mode="jenks"
jenksK={5}
/>
// Mostrar municipios de múltiples entidades
<MapaPMTiles
csvUrl="https://example.com/datos_municipales.csv"
fitToIds={["09", "15", "14"]}
showMunicipios={true}
/>Formato CSV para municipios:
cvegeo,nombre,valor
09002,Azcapotzalco,150
09003,Coyoacán,200
09010,Álvaro Obregón,175Colores Personalizados
Nuevo en v1.12.: Personaliza completamente los colores de tus mapas.
Modo Boolean
Especifica dos colores: [colorFalse, colorTrue]
// Colores azules
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
mode="boolean"
color={['#e3f2fd', '#1976d2']} // azul claro → azul oscuro
/>
// Colores rojos
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
mode="boolean"
color={['#ffebee', '#c62828']} // rojo claro → rojo oscuro
/>Modo Jenks - Rampa automática
Especifica dos colores y se genera una rampa automática:
// Rampa de naranjas
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
mode="jenks"
jenksK={5}
color={['#fff3e0', '#e65100']} // naranja claro → naranja oscuro
/>
// Rampa de verdes
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
mode="jenks"
jenksK={7}
color={['#e8f5e9', '#1b5e20']} // verde claro → verde oscuro
/>Modo Jenks - Colores exactos por clase
Especifica exactamente tantos colores como clases:
// 4 clases = 4 colores exactos
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
mode="jenks"
jenksK={4}
color={['#fff9c4', '#ffeb3b', '#fbc02d', '#f57f17']}
/>
// 3 clases = 3 colores exactos
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
mode="jenks"
jenksK={3}
color={['#bbdefb', '#42a5f5', '#0d47a1']}
/>Colores para municipios
Usa colorMunicipios para colores diferentes en el nivel municipal:
// Entidades verdes, municipios azules
<MapaPMTiles
csvUrl="https://example.com/datos_entidades.csv"
mode="jenks"
color={['#e8f5e9', '#2e7d32']} // verdes para entidades
fitToIds={["09", "15", "14"]}
csvUrlMunicipios="https://example.com/datos_municipios.csv"
modeMunicipios="jenks"
colorMunicipios={['#e3f2fd', '#1565c0']} // azules para municipios
/>
// Boolean para entidades, Jenks custom para municipios
<MapaPMTiles
csvUrl="https://example.com/datos_entidades.csv"
mode="boolean"
color={['#ffccbc', '#d84315']} // naranjas
fitToIds={["09", "15"]}
csvUrlMunicipios="https://example.com/datos_municipios.csv"
modeMunicipios="jenks"
jenksK={6}
colorMunicipios={['#f3e5f5', '#6a1b9a']} // púrpuras
/>Nota: Si no especificas
colorocolorMunicipios, se usan los colores predeterminados (#f3f3f3y#66827f).
Popup Interactivo
Habilita popups que se muestran al pasar el mouse:
// Popup simple (solo nombre)
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
fitToIds="09"
enablePopup={true}
/>
// Popup con datos del CSV
<MapaPMTiles
csvUrl="https://example.com/datos_poblacion.csv"
field="poblacion"
fitToIds="09"
enablePopup={true}
popupDataLabel="Población total"
popupDataField="poblacion"
/>
// Popup en modo municipios
<MapaPMTiles
csvUrl="https://example.com/datos_municipales.csv"
fitToIds="09"
showMunicipios={true}
enablePopup={true}
popupDataLabel="Habitantes"
popupDataField="poblacion"
mode="jenks"
/>Comportamiento:
- Se muestra al pasar el mouse (hover)
- Entidades: Usa diccionario interno (ej: "09" → "Ciudad de México")
- Municipios: Usa el campo
nomgeodel PMTiles - Números formateados automáticamente con comas
Interactividad y Drill-Down
Click para explorar municipios
Cuando especificas 2 o más entidades en fitToIds, el mapa se vuelve interactivo:
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
fitToIds={["09", "15", "14"]}
mode="jenks"
/>Comportamiento:
- Vista inicial: Muestra las 3 entidades con relleno
- Click en una entidad: Hace zoom y cambia a vista municipal
- Volver atrás: Presiona
ESCo doble click
Ejemplo completo con todas las features
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
fitToIds={["09", "15", "14"]}
mode="jenks"
jenksK={5}
color={['#e8f5e9', '#2e7d32']}
enablePopup={true}
popupDataLabel="Población"
popupDataField="poblacion"
/>CSV Dual (Entidades + Municipios)
Usa fuentes de datos separadas para entidades y municipios:
// Vista inicial: población total por entidad
// Después del click: densidad poblacional por municipio
<MapaPMTiles
// CSV para entidades
csvUrl="https://example.com/datos_entidades.csv"
field="poblacion_total"
// CSV para municipios
csvUrlMunicipios="https://example.com/datos_municipios.csv"
fieldMunicipios="densidad"
fitToIds={["09", "15", "14"]}
mode="jenks"
jenksK={5}
/>Con archivo local para municipios
<MapaPMTiles
csvUrl="https://example.com/datos_entidades.csv"
field="valor"
csvFileMunicipios={archivoMunicipios}
fieldMunicipios="otro_campo"
fitToIds={["09", "15"]}
mode="boolean"
/>Con popup y CSV dual
<MapaPMTiles
// Entidades: clasificación booleana
csvUrl="https://example.com/datos_entidades.csv"
field="tiene_cobertura"
mode="boolean"
// Municipios: clasificación Jenks
csvUrlMunicipios="https://example.com/datos_municipios.csv"
fieldMunicipios="poblacion"
modeMunicipios="jenks"
fitToIds={["09", "15", "14"]}
jenksK={5}
// Popup adaptativo
enablePopup={true}
popupDataLabel="Habitantes"
popupDataField="poblacion"
/>Comportamiento del popup con CSV dual:
- Vista de entidades: Solo muestra el nombre (sin datos adicionales)
- Vista de municipios: Muestra nombre + valor del CSV municipal
Modos de Estilo
Modo Boolean
Pinta las geometrías en dos colores según el valor.
Colores por defecto:
value === 1→#66827f(verde azulado)value === 0 / null / undefined→#f3f3f3(gris claro)
Con colores personalizados:
<MapaPMTiles
mode="boolean"
color={['#e3f2fd', '#1976d2']} // [colorFalse, colorTrue]
/>Sin colores personalizados:
<MapaPMTiles mode="boolean" />Modo Jenks
Clasifica los valores numéricos usando el algoritmo Jenks Natural Breaks.
Colores por defecto:
- De
#f3f3f3(gris claro) a#66827f(verde azulado) - Número de clases controlado por
jenksK(default: 5)
Con rampa automática:
<MapaPMTiles
mode="jenks"
jenksK={5}
color={['#fff3e0', '#e65100']} // [colorMin, colorMax]
/>Con colores exactos:
<MapaPMTiles
mode="jenks"
jenksK={4}
color={['#fff9c4', '#ffeb3b', '#fbc02d', '#f57f17']} // 4 colores
/>Sin colores personalizados:
<MapaPMTiles mode="jenks" jenksK={7} />Props de MapaPMTiles
Props Obligatorias
| Prop | Tipo | Descripción |
|------|------|-------------|
| csvUrl o csvFile | string \| File | URL del CSV remoto o archivo File local |
Props de Datos
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| pmtilesUrl | string | URL de entidades de México | URL del archivo PMTiles remoto |
| sourceLayer | string | "entidad" | Nombre de la capa vectorial en el PMTiles |
| joinGeomKey | string | "cvegeo" | Campo de la geometría para el join |
| joinCsvKey | string | joinGeomKey | Campo del CSV para el join |
| field | string | "valor" | Campo del CSV con los valores a visualizar |
Props de Visualización
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| mode | "boolean" \| "jenks" | "boolean" | Modo de estilo |
| jenksK | number | 5 | Número de clases para Jenks |
| color | [string, string] \| string[] | ['#f3f3f3', '#66827f'] | v1.12.1: Colores personalizados. Boolean: [colorFalse, colorTrue]. Jenks: [colorMin, colorMax] o array exacto |
| width | string \| number | "100%" | Ancho del mapa |
| height | string \| number | 520 | Alto del mapa (px si es número) |
Props de Navegación
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| initialView | object | {center: [-102, 23], zoom: 4} | Vista inicial (ignorado si hay fitToIds) |
| initialView.center | [number, number] | [-102, 23] | Centro inicial [lng, lat] |
| initialView.zoom | number | 4 | Zoom inicial |
| fitToIds | string \| string[] | undefined | IDs de features para filtrar y zoom automático |
| bboxField | string | "bbox" | Campo con bbox precalculado |
Props de Municipios
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| showMunicipios | boolean | false | Activa modo municipal |
| csvUrlMunicipios | string | undefined | URL del CSV para municipios |
| csvFileMunicipios | File | undefined | Archivo File para municipios |
| joinCsvKeyMunicipios | string | "cvegeo" | Campo del CSV municipal para join |
| fieldMunicipios | string | field | Campo del CSV municipal a visualizar |
| modeMunicipios | "boolean" \| "jenks" | mode | Modo de estilo para municipios |
| colorMunicipios | [string, string] \| string[] | color | v1.12.1: Colores para municipios |
Props de Interactividad
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| enablePopup | boolean | false | Habilita popup con hover |
| popupDataLabel | string | undefined | Etiqueta para el dato del popup |
| popupDataField | string | undefined | Campo del CSV para el popup |
| onFeatureClick | (id: string, props: any) => void | undefined | Callback al hacer click (solo con 2+ entidades) |
Formato CSV
El archivo CSV debe tener:
- Header row con nombres de columnas
- Una columna con el join key que coincida con
joinGeomKey - Una columna con los valores especificada en
field
Ejemplo:
cvegeo,nombre,valor
01,Aguascalientes,1
02,Baja California,0
09,Ciudad de México,1TotalesDisplay
Componente para mostrar totales y estadísticas de manera flexible y responsive.
Características
- Tres formas de uso: Datos hardcodeados, CSV por URL o archivo local
- Responsive: Se adapta a desktop, tablet y mobile
- Centrado por defecto: Posicionamiento configurable
- Personalizable: Formateadores custom para labels y valores
- TypeScript: Completamente tipado
Uso Básico
Importar
import { TotalesDisplay } from '@datosgeo-atdt/geo-ui';
import '@datosgeo-atdt/geo-ui/style.css';Datos hardcodeados
<TotalesDisplay
items={[
{ label: "Total de caminos abiertos", value: 496 },
{ label: "Total de caminos cerrados", value: 9 },
]}
/>Datos desde CSV (URL)
<TotalesDisplay
csvUrl="https://example.com/datos.csv"
joinCsvKey="tipo"
field="cantidad"
labelFormatter={(key) => `Total de ${key.toLowerCase()}`}
valueFormatter={(value) => value.toLocaleString('es-MX')}
/>Datos desde archivo local
import { useState } from 'react';
function App() {
const [csvFile, setCsvFile] = useState<File | null>(null);
return (
<div>
<input
type="file"
accept=".csv"
onChange={(e) => setCsvFile(e.target.files?.[0] || null)}
/>
{csvFile && (
<TotalesDisplay
csvFile={csvFile}
joinCsvKey="id"
field="total"
labelFormatter={(key) => `Categoría ${key}`}
/>
)}
</div>
);
}Con filtro específico
<TotalesDisplay
csvUrl="https://example.com/datos.csv"
joinCsvKey="region"
field="poblacion"
filterKey="CDMX"
labelFormatter={(key) => `Población de ${key}`}
valueFormatter={(value) => `${value.toLocaleString('es-MX')} habitantes`}
/>Integrando con MapaPMTiles
<div>
<TotalesDisplay
items={[
{ label: "Total de caminos abiertos", value: 496 },
{ label: "Total de caminos cerrados", value: 9 },
]}
/>
<MapaPMTiles
csvUrl="https://example.com/datos.csv"
fitToIds={["09", "15", "14"]}
mode="jenks"
enablePopup={true}
/>
</div>Props de TotalesDisplay
Props de Datos (una es requerida)
| Prop | Tipo | Descripción |
|------|------|-------------|
| items | TotalItem[] | Array de objetos con label y value |
| csvUrl | string | URL del CSV remoto |
| csvFile | File | Archivo File local |
Props de Configuración CSV
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| joinCsvKey | string | "key" | Campo del CSV como identificador |
| field | string | "valor" | Campo del CSV con valores |
| filterKey | string | undefined | Mostrar solo este key |
Props de Visualización
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| centered | boolean | true | Contenedor centrado |
| className | string | "" | Clases CSS adicionales |
| labelFormatter | (key: string, value: any) => string | undefined | Formatear label |
| valueFormatter | (value: any) => string \| number | undefined | Formatear valor |
Tipo TotalItem
interface TotalItem {
label: string;
value: number | string;
}Responsive
- Desktop: Layout horizontal con espaciado amplio (13.89vw)
- Tablet (601px - 1024px): Espaciado medio (8vw)
- Mobile (≤600px): Layout vertical centrado
DataTable
Componente de tabla genérico y flexible con soporte para carga automática de CSV.
Características
- Carga automática de CSV: Lee archivos desde
public/ - Detección automática de columnas: Extrae nombres del CSV
- Columnas personalizables: Define qué mostrar y anchos
- Formato automático: Números con separadores de miles
- Índice opcional: Numeración de filas
- Responsive: Se adapta a móvil
- Interactividad: Callback
onRowClick
Uso Básico
Importar
import { DataTable } from '@datosgeo-atdt/geo-ui';
import '@datosgeo-atdt/geo-ui/style.css';Cargar CSV desde public/
Si tienes public/alcaldias.csv:
alcaldia,poblacion
Iztapalapa,1815786
Gustavo A. Madero,1185772
Álvaro Obregón,749982Simplemente:
<DataTable csvPath="/alcaldias.csv" />Auto-detecta:
- Nombres de columnas (
alcaldia,poblacion) - Parsea datos y formatea números (1,815,786)
- Distribuye columnas equitativamente (50% cada una)
Personalizar columnas
<DataTable
csvPath="/alcaldias.csv"
columns={[
{ key: 'alcaldia', label: 'Alcaldía', width: '60%' },
{ key: 'poblacion', label: 'Población Total', width: '40%' }
]}
showIndex={true}
indexLabel="#"
/>Datos directos (sin CSV)
const datos = [
{ nombre: 'Ciudad de México', habitantes: 9209944 },
{ nombre: 'Guadalajara', habitantes: 1495189 },
{ nombre: 'Monterrey', habitantes: 1142994 }
];
<DataTable
data={datos}
columns={[
{ key: 'nombre', label: 'Ciudad' },
{ key: 'habitantes', label: 'Habitantes' }
]}
/>Integración con MapaPMTiles
Layout dashboard con mapa y tabla:
<div style={{ display: 'flex', width: '100%', height: '100vh' }}>
{/* Mapa 50% */}
<MapaPMTiles
csvUrl="/datos_entidades.csv"
fitToIds={["09", "15", "14"]}
mode="jenks"
enablePopup={true}
/>
{/* Tabla 50% */}
<DataTable
csvPath="/datos_entidades.csv"
columns={[
{ key: 'entidad', label: 'Entidad' },
{ key: 'valor', label: 'Valor' }
]}
/>
</div>Interactividad bidireccional (Tabla ↔ Mapa)
import { useState } from 'react';
function App() {
const [nivel, setNivel] = useState<'entidad' | 'municipio'>('entidad');
const [selectedEnt, setSelectedEnt] = useState<string | null>(null);
return (
<div style={{ display: 'flex', width: '100%', height: '100vh' }}>
{/* Mapa con click handler */}
<MapaPMTiles
csvUrl={nivel === 'entidad' ? '/entidades.csv' : '/municipios.csv'}
fitToIds={selectedEnt ? [selectedEnt] : undefined}
mode="jenks"
showMunicipios={nivel === 'municipio'}
enablePopup={true}
onFeatureClick={(featureId) => {
if (nivel === 'entidad') {
setSelectedEnt(featureId);
setNivel('municipio');
}
}}
/>
{/* Tabla con click handler */}
<DataTable
csvPath={nivel === 'entidad' ? '/entidades.csv' : '/municipios.csv'}
onRowClick={(row) => {
if (nivel === 'entidad') {
setSelectedEnt(row.cvegeo);
setNivel('municipio');
}
}}
/>
{/* Botón para regresar */}
{nivel === 'municipio' && (
<button onClick={() => { setNivel('entidad'); setSelectedEnt(null); }}>
← Regresar
</button>
)}
</div>
);
}Props de DataTable
Props de Datos (una es requerida)
| Prop | Tipo | Descripción |
|------|------|-------------|
| data | Record<string, any>[] | Array de objetos |
| csvPath | string | Ruta del CSV en public/ |
Props de Configuración
| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| columns | DataTableColumn[] | Auto-detectado | Definición de columnas |
| width | string | Por CSS | Ancho del contenedor (50% desktop, 100% mobile) |
| height | string | Por CSS | Alto del contenedor (scroll si > 70vh) |
| className | string | "" | Clases CSS adicionales |
| showIndex | boolean | false | Mostrar índice numérico |
| indexLabel | string | "#" | Etiqueta para índice |
| onRowClick | (row: Record<string, any>, index: number) => void | undefined | Callback al hacer click en fila |
Tipo DataTableColumn
interface DataTableColumn {
key: string; // Campo del objeto/CSV
label: string; // Texto del header
width?: string; // Ancho de columna (ej: "40%", "200px")
}Tecnologías
- React 18+
- TypeScript
- MapLibre GL JS: Renderizado de mapas vectoriales
- PMTiles: Formato de tiles vectoriales eficiente
- PapaParse: Parsing de CSV
- Vite: Build tool
Licencia
ISC
Autor
Dirección de Datos Geográficos - ATDT
Contribuciones
Issues y pull requests son bienvenidos en GitLab.
Notas CORS
Para consumir PMTiles y CSV de dominios externos:
- El servidor debe tener CORS configurado
- Para PMTiles, debe soportar Range requests (HTTP 206)
- Headers necesarios:
Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Range Accept-Ranges: bytes
