@datosgeo-atdt/geo-ui 1.11.14 → 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,42 +1,46 @@
1
- # @atdt/geo-ui
1
+ # @datosgeo-atdt/geo-ui
2
2
 
3
3
  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).
4
4
 
5
- ## Características
5
+ ## Novedades en v1.12
6
+
7
+ **Colores personalizados para mapas**: Ahora puedes personalizar completamente los colores de tus mapas con las nuevas props `color` y `colorMunicipios`.
8
+
9
+ - **Modo Boolean**: Define colores para valores verdaderos y falsos
10
+ - **Modo Jenks**: Genera rampas automáticas entre dos colores o especifica colores exactos para cada clase
11
+ - **Municipios**: Colores independientes para drill-down municipal
12
+ - **Retrocompatible**: Si no especificas colores, usa los defaults actuales
13
+
14
+ [Ver ejemplos de colores personalizados](#-colores-personalizados)
6
15
 
7
- - **MapaPMTiles**: Componente para renderizar mapas vectoriales usando MapLibre GL y PMTiles
8
- - **TotalesDisplay**: Componente para mostrar totales y estadísticas con soporte responsive
9
- - **DataTable**: Componente de tabla flexible con carga automática de CSV
10
- - **Join CSV**: Unión automática de datos tabulares con geometrías vectoriales
11
- - **Estilos temáticos**: Soporte para modo booleano y clasificación Jenks
12
- - **TypeScript**: Completamente tipado para mejor experiencia de desarrollo
13
- - **Sin SSR**: Diseñado para aplicaciones client-side (React puro, Vite, CRA)
16
+ ---
14
17
 
15
18
  ## Instalación
16
19
 
17
20
  ```bash
18
- npm install @atdt/geo-ui maplibre-gl pmtiles papaparse @mapbox/vector-tile pbf
21
+ npm install @datosgeo-atdt/geo-ui maplibre-gl pmtiles papaparse @mapbox/vector-tile pbf
19
22
  ```
20
23
 
21
24
  **Importante**: Las dependencias `react` y `react-dom` son peer dependencies (versión 18+).
22
25
 
23
- ## Uso Básico
26
+ ---
27
+
28
+ ## Inicio Rápido
24
29
 
25
- ### Importar el componente
30
+ ### Importar componentes
26
31
 
27
32
  ```tsx
28
- import { MapaPMTiles } from '@atdt/geo-ui';
29
- import '@atdt/geo-ui/style.css';
33
+ import { MapaPMTiles, TotalesDisplay, DataTable } from '@datosgeo-atdt/geo-ui';
34
+ import '@datosgeo-atdt/geo-ui/style.css';
30
35
  ```
31
36
 
32
- ### Ejemplo básico (usando valores por defecto)
37
+ ### Ejemplo mínimo
33
38
 
34
- La biblioteca incluye **integrada** la URL del PMTiles de entidades de México, por lo que no necesitas especificar `pmtilesUrl`, `sourceLayer` ni `joinGeomKey` si trabajas con entidades:
39
+ La biblioteca incluye **integrada** la URL del PMTiles de entidades de México, por lo que no necesitas especificar `pmtilesUrl`, `sourceLayer` ni `joinGeomKey`:
35
40
 
36
41
  ```tsx
37
- import React from 'react';
38
- import { MapaPMTiles } from '@atdt/geo-ui';
39
- import '@atdt/geo-ui/style.css';
42
+ import { MapaPMTiles } from '@datosgeo-atdt/geo-ui';
43
+ import '@datosgeo-atdt/geo-ui/style.css';
40
44
 
41
45
  function App() {
42
46
  return (
@@ -44,46 +48,58 @@ function App() {
44
48
  csvUrl="https://example.com/datos.csv"
45
49
  field="valor"
46
50
  mode="boolean"
47
- width="100%"
48
- height={600}
49
51
  />
50
52
  );
51
53
  }
52
-
53
- export default App;
54
54
  ```
55
55
 
56
- ### Ejemplo con csvUrl (especificando PMTiles personalizado)
56
+ ---
57
57
 
58
- ```tsx
59
- import React from 'react';
60
- import { MapaPMTiles } from '@atdt/geo-ui';
61
- import '@atdt/geo-ui/style.css';
58
+ ## Componentes
62
59
 
63
- function App() {
64
- return (
65
- <MapaPMTiles
66
- pmtilesUrl="https://example.com/custom.pmtiles"
67
- sourceLayer="mi-capa"
68
- joinGeomKey="ID"
69
- csvUrl="https://example.com/datos.csv"
70
- field="valor"
71
- mode="boolean"
72
- width="100%"
73
- height={600}
74
- />
75
- );
76
- }
60
+ - **[MapaPMTiles](#-mapapmtiles)**: Mapas vectoriales interactivos con PMTiles
61
+ - **[TotalesDisplay](#-totalesdisplay)**: Visualización de totales y estadísticas
62
+ - **[DataTable](#-datatable)**: Tablas de datos con carga de CSV
63
+
64
+ ---
65
+
66
+ # MapaPMTiles
67
+
68
+ Componente para renderizar mapas vectoriales usando MapLibre GL y PMTiles con soporte para unión de datos CSV y estilos temáticos.
77
69
 
78
- export default App;
70
+ ## Características
71
+
72
+ - **PMTiles integrado**: URL de entidades de México por defecto
73
+ - **Join CSV**: Unión automática de datos tabulares con geometrías
74
+ - **Estilos temáticos**: Modo booleano y clasificación Jenks
75
+ - **Colores personalizados**: Define tus propias paletas (v1.12.1+)
76
+ - **Drill-down**: Click para explorar municipios
77
+ - **Popup interactivo**: Información al pasar el mouse
78
+ - **TypeScript**: Completamente tipado
79
+
80
+ ---
81
+
82
+ ## Guía de Uso
83
+
84
+ ### Uso Básico
85
+
86
+ #### Con CSV remoto (URL)
87
+
88
+ ```tsx
89
+ <MapaPMTiles
90
+ csvUrl="https://example.com/datos.csv"
91
+ field="valor"
92
+ mode="boolean"
93
+ width="100%"
94
+ height={600}
95
+ />
79
96
  ```
80
97
 
81
- ### Ejemplo con csvFile (archivo local)
98
+ #### Con archivo CSV local
82
99
 
83
100
  ```tsx
84
- import React, { useState } from 'react';
85
- import { MapaPMTiles } from '@atdt/geo-ui';
86
- import '@atdt/geo-ui/style.css';
101
+ import { useState } from 'react';
102
+ import { MapaPMTiles } from '@datosgeo-atdt/geo-ui';
87
103
 
88
104
  function App() {
89
105
  const [csvFile, setCsvFile] = useState<File | null>(null);
@@ -106,13 +122,28 @@ function App() {
106
122
  </div>
107
123
  );
108
124
  }
125
+ ```
109
126
 
110
- export default App;
127
+ #### Con PMTiles personalizado
128
+
129
+ ```tsx
130
+ <MapaPMTiles
131
+ pmtilesUrl="https://example.com/custom.pmtiles"
132
+ sourceLayer="mi-capa"
133
+ joinGeomKey="ID"
134
+ csvUrl="https://example.com/datos.csv"
135
+ field="valor"
136
+ mode="boolean"
137
+ />
111
138
  ```
112
139
 
113
- ### Ejemplo con fitToIds (zoom y filtrado por entidades)
140
+ ---
141
+
142
+ ### Filtrado y Zoom
143
+
144
+ #### Mostrar entidades específicas
114
145
 
115
- Muestra **solo** las entidades seleccionadas y ajusta el mapa automáticamente a su extensión (sin animación):
146
+ Usa `fitToIds` para mostrar **solo** las entidades seleccionadas y ajustar el mapa automáticamente:
116
147
 
117
148
  ```tsx
118
149
  // Mostrar solo Ciudad de México
@@ -121,29 +152,31 @@ Muestra **solo** las entidades seleccionadas y ajusta el mapa automáticamente a
121
152
  fitToIds="09"
122
153
  />
123
154
 
124
- // Mostrar múltiples entidades (Ciudad de México, Estado de México y Jalisco)
155
+ // Mostrar múltiples entidades (CDMX, Edomex y Jalisco)
125
156
  <MapaPMTiles
126
157
  csvUrl="https://example.com/datos.csv"
127
158
  fitToIds={["09", "15", "14"]}
128
159
  />
129
160
  ```
130
161
 
131
- **Ventajas de usar `fitToIds`:**
132
- - No necesitas configurar `pmtilesUrl` (está integrado)
162
+ **Ventajas:**
133
163
  - Filtra automáticamente para mostrar solo las entidades seleccionadas
134
164
  - Calcula y ajusta el bbox combinado sin animación de zoom
135
165
  - Carga directo en la vista correcta
136
166
 
137
- ### Ejemplo con showMunicipios (visualización municipal)
167
+ ---
168
+
169
+ ### Visualización Municipal
138
170
 
139
- Cuando activas `showMunicipios={true}`, el componente cambia a **nivel municipal**:
140
- - La **entidad** se muestra solo como **contorno** (outline grueso)
141
- - Los **municipios** dentro de esa entidad se muestran con el **relleno temático** (boolean o jenks)
142
- - Los datos CSV se unen usando el **cvegeo municipal** (5 dígitos)
171
+ #### Modo municipios básico
172
+
173
+ Cuando activas `showMunicipios={true}`:
174
+ - La **entidad** se muestra solo como **contorno**
175
+ - Los **municipios** dentro de esa entidad se muestran con el **relleno temático**
143
176
 
144
177
  ```tsx
145
- // Mostrar municipios de Ciudad de México (09)
146
- // El CSV debe tener cvegeo municipal (ej: "09002", "09010", etc.)
178
+ // Mostrar municipios de Ciudad de México
179
+ // El CSV debe tener cvegeo municipal (5 dígitos: "09002", "09010", etc.)
147
180
  <MapaPMTiles
148
181
  csvUrl="https://example.com/datos_municipales.csv"
149
182
  fitToIds="09"
@@ -160,12 +193,6 @@ Cuando activas `showMunicipios={true}`, el componente cambia a **nivel municipal
160
193
  />
161
194
  ```
162
195
 
163
- **¿Cómo funciona?**
164
- 1. `fitToIds="09"` extrae automáticamente `cve_ent="09"` (primeros 2 dígitos)
165
- 2. Filtra y muestra **todos los municipios** con `cve_ent="09"`
166
- 3. La entidad "09" se dibuja solo como contorno
167
- 4. Los municipios se rellenan según los valores del CSV unidos por `cvegeo` (5 dígitos)
168
-
169
196
  **Formato CSV para municipios:**
170
197
  ```csv
171
198
  cvegeo,nombre,valor
@@ -174,12 +201,119 @@ cvegeo,nombre,valor
174
201
  09010,Álvaro Obregón,175
175
202
  ```
176
203
 
177
- ### Ejemplo con Popup (información al pasar el mouse)
204
+ ---
205
+
206
+ ### Colores Personalizados
207
+
208
+ **Nuevo en v1.12.**: Personaliza completamente los colores de tus mapas.
209
+
210
+ #### Modo Boolean
211
+
212
+ Especifica dos colores: `[colorFalse, colorTrue]`
213
+
214
+ ```tsx
215
+ // Colores azules
216
+ <MapaPMTiles
217
+ csvUrl="https://example.com/datos.csv"
218
+ mode="boolean"
219
+ color={['#e3f2fd', '#1976d2']} // azul claro → azul oscuro
220
+ />
221
+
222
+ // Colores rojos
223
+ <MapaPMTiles
224
+ csvUrl="https://example.com/datos.csv"
225
+ mode="boolean"
226
+ color={['#ffebee', '#c62828']} // rojo claro → rojo oscuro
227
+ />
228
+ ```
229
+
230
+ #### Modo Jenks - Rampa automática
231
+
232
+ Especifica dos colores y se genera una rampa automática:
233
+
234
+ ```tsx
235
+ // Rampa de naranjas
236
+ <MapaPMTiles
237
+ csvUrl="https://example.com/datos.csv"
238
+ mode="jenks"
239
+ jenksK={5}
240
+ color={['#fff3e0', '#e65100']} // naranja claro → naranja oscuro
241
+ />
242
+
243
+ // Rampa de verdes
244
+ <MapaPMTiles
245
+ csvUrl="https://example.com/datos.csv"
246
+ mode="jenks"
247
+ jenksK={7}
248
+ color={['#e8f5e9', '#1b5e20']} // verde claro → verde oscuro
249
+ />
250
+ ```
251
+
252
+ #### Modo Jenks - Colores exactos por clase
178
253
 
179
- Puedes habilitar un popup que se muestra al pasar el mouse sobre las features:
254
+ Especifica exactamente tantos colores como clases:
180
255
 
181
256
  ```tsx
182
- // Popup simple: solo muestra el nombre de la entidad/municipio
257
+ // 4 clases = 4 colores exactos
258
+ <MapaPMTiles
259
+ csvUrl="https://example.com/datos.csv"
260
+ mode="jenks"
261
+ jenksK={4}
262
+ color={['#fff9c4', '#ffeb3b', '#fbc02d', '#f57f17']}
263
+ />
264
+
265
+ // 3 clases = 3 colores exactos
266
+ <MapaPMTiles
267
+ csvUrl="https://example.com/datos.csv"
268
+ mode="jenks"
269
+ jenksK={3}
270
+ color={['#bbdefb', '#42a5f5', '#0d47a1']}
271
+ />
272
+ ```
273
+
274
+ #### Colores para municipios
275
+
276
+ Usa `colorMunicipios` para colores diferentes en el nivel municipal:
277
+
278
+ ```tsx
279
+ // Entidades verdes, municipios azules
280
+ <MapaPMTiles
281
+ csvUrl="https://example.com/datos_entidades.csv"
282
+ mode="jenks"
283
+ color={['#e8f5e9', '#2e7d32']} // verdes para entidades
284
+
285
+ fitToIds={["09", "15", "14"]}
286
+
287
+ csvUrlMunicipios="https://example.com/datos_municipios.csv"
288
+ modeMunicipios="jenks"
289
+ colorMunicipios={['#e3f2fd', '#1565c0']} // azules para municipios
290
+ />
291
+
292
+ // Boolean para entidades, Jenks custom para municipios
293
+ <MapaPMTiles
294
+ csvUrl="https://example.com/datos_entidades.csv"
295
+ mode="boolean"
296
+ color={['#ffccbc', '#d84315']} // naranjas
297
+
298
+ fitToIds={["09", "15"]}
299
+
300
+ csvUrlMunicipios="https://example.com/datos_municipios.csv"
301
+ modeMunicipios="jenks"
302
+ jenksK={6}
303
+ colorMunicipios={['#f3e5f5', '#6a1b9a']} // púrpuras
304
+ />
305
+ ```
306
+
307
+ > **Nota**: Si no especificas `color` o `colorMunicipios`, se usan los colores predeterminados (`#f3f3f3` y `#66827f`).
308
+
309
+ ---
310
+
311
+ ### Popup Interactivo
312
+
313
+ Habilita popups que se muestran al pasar el mouse:
314
+
315
+ ```tsx
316
+ // Popup simple (solo nombre)
183
317
  <MapaPMTiles
184
318
  csvUrl="https://example.com/datos.csv"
185
319
  fitToIds="09"
@@ -208,20 +342,21 @@ Puedes habilitar un popup que se muestra al pasar el mouse sobre las features:
208
342
  />
209
343
  ```
210
344
 
211
- **Comportamiento del popup:**
212
- - Se muestra al pasar el mouse sobre las features (hover)
213
- - **Nombre**: Muestra automáticamente el nombre de la entidad o municipio
214
- - Entidades: usa un diccionario interno (ej: "09" → "Ciudad de México")
215
- - Municipios: usa el campo `nomgeo` del PMTiles
216
- - **Datos adicionales**: Si especificas `popupDataLabel` y `popupDataField`, muestra el valor del CSV
217
- - Los números se formatean automáticamente con comas (ej: 1,234,567)
345
+ **Comportamiento:**
346
+ - Se muestra al pasar el mouse (hover)
347
+ - **Entidades**: Usa diccionario interno (ej: "09" "Ciudad de México")
348
+ - **Municipios**: Usa el campo `nomgeo` del PMTiles
349
+ - Números formateados automáticamente con comas
350
+
351
+ ---
352
+
353
+ ### Interactividad y Drill-Down
218
354
 
219
- ### Ejemplo con Interactividad (click para drill-down)
355
+ #### Click para explorar municipios
220
356
 
221
- Cuando especificas **2 o más entidades** en `fitToIds`, el mapa se vuelve interactivo automáticamente:
357
+ Cuando especificas **2 o más entidades** en `fitToIds`, el mapa se vuelve interactivo:
222
358
 
223
359
  ```tsx
224
- // Vista inicial: 3 entidades con visualización jenks
225
360
  <MapaPMTiles
226
361
  csvUrl="https://example.com/datos.csv"
227
362
  fitToIds={["09", "15", "14"]}
@@ -229,49 +364,41 @@ Cuando especificas **2 o más entidades** en `fitToIds`, el mapa se vuelve inter
229
364
  />
230
365
  ```
231
366
 
232
- **Comportamiento interactivo:**
233
- 1. **Vista inicial**: Muestra las 3 entidades con relleno (jenks/boolean)
234
- 2. **Click en una entidad**:
235
- - Hace zoom hacia esa entidad
236
- - Cambia automáticamente a vista municipal
237
- - Muestra municipios con relleno clasificado
238
- - La entidad se muestra solo como contorno
239
- 3. **Volver atrás**:
240
- - Presiona `ESC`
241
- - O haz doble click en el mapa
242
-
243
- **Ejemplo completo con todas las features:**
367
+ **Comportamiento:**
368
+ 1. **Vista inicial**: Muestra las 3 entidades con relleno
369
+ 2. **Click en una entidad**: Hace zoom y cambia a vista municipal
370
+ 3. **Volver atrás**: Presiona `ESC` o doble click
371
+
372
+ #### Ejemplo completo con todas las features
373
+
244
374
  ```tsx
245
375
  <MapaPMTiles
246
376
  csvUrl="https://example.com/datos.csv"
247
377
  fitToIds={["09", "15", "14"]}
248
378
  mode="jenks"
249
379
  jenksK={5}
380
+ color={['#e8f5e9', '#2e7d32']}
250
381
  enablePopup={true}
251
382
  popupDataLabel="Población"
252
383
  popupDataField="poblacion"
253
384
  />
254
385
  ```
255
386
 
256
- Esto crea una experiencia de exploración completa:
257
- - Vista general de 3 entidades
258
- - Click para explorar municipios
259
- - Popup con información al pasar el mouse
260
- - Clasificación jenks en ambos niveles
387
+ ---
261
388
 
262
- ### Ejemplo con CSV dual (entidades y municipios con datos diferentes)
389
+ ### CSV Dual (Entidades + Municipios)
263
390
 
264
- Puedes usar **fuentes de datos separadas** para entidades y municipios. Cuando el usuario hace click en una entidad, los municipios se visualizarán con el CSV municipal:
391
+ Usa **fuentes de datos separadas** para entidades y municipios:
265
392
 
266
393
  ```tsx
267
- // Vista inicial: entidades con datos de población total
268
- // Después del click: municipios con datos de densidad poblacional
394
+ // Vista inicial: población total por entidad
395
+ // Después del click: densidad poblacional por municipio
269
396
  <MapaPMTiles
270
- // CSV para entidades (vista inicial)
397
+ // CSV para entidades
271
398
  csvUrl="https://example.com/datos_entidades.csv"
272
399
  field="poblacion_total"
273
400
 
274
- // CSV para municipios (después del click)
401
+ // CSV para municipios
275
402
  csvUrlMunicipios="https://example.com/datos_municipios.csv"
276
403
  fieldMunicipios="densidad"
277
404
 
@@ -281,7 +408,8 @@ Puedes usar **fuentes de datos separadas** para entidades y municipios. Cuando e
281
408
  />
282
409
  ```
283
410
 
284
- **Ejemplo con archivo local para municipios:**
411
+ #### Con archivo local para municipios
412
+
285
413
  ```tsx
286
414
  <MapaPMTiles
287
415
  csvUrl="https://example.com/datos_entidades.csv"
@@ -295,28 +423,16 @@ Puedes usar **fuentes de datos separadas** para entidades y municipios. Cuando e
295
423
  />
296
424
  ```
297
425
 
298
- **¿Cómo funciona?**
299
- 1. **Vista inicial**: Muestra las entidades coloreadas según el CSV de entidades
300
- 2. **Click en una entidad**:
301
- - Si especificaste `csvUrlMunicipios` o `csvFileMunicipios`, carga ese CSV
302
- - Recalcula la clasificación Jenks con los datos municipales
303
- - Aplica los nuevos colores a los municipios
304
- - **Actualiza automáticamente el popup** para mostrar datos del CSV municipal
305
- 3. **Ventajas**:
306
- - Diferentes métricas para diferentes niveles (ej: totales en entidades, densidades en municipios)
307
- - Archivos CSV más pequeños y específicos para cada nivel
308
- - Mayor flexibilidad en la visualización de datos
309
- - Los popups se actualizan automáticamente según el nivel visualizado
310
-
311
- **Ejemplo completo con popup y CSV dual:**
426
+ #### Con popup y CSV dual
427
+
312
428
  ```tsx
313
429
  <MapaPMTiles
314
- // Vista inicial: entidades con clasificación booleana
430
+ // Entidades: clasificación booleana
315
431
  csvUrl="https://example.com/datos_entidades.csv"
316
432
  field="tiene_cobertura"
317
433
  mode="boolean"
318
434
 
319
- // Drill-down: municipios con clasificación Jenks
435
+ // Municipios: clasificación Jenks
320
436
  csvUrlMunicipios="https://example.com/datos_municipios.csv"
321
437
  fieldMunicipios="poblacion"
322
438
  modeMunicipios="jenks"
@@ -324,9 +440,7 @@ Puedes usar **fuentes de datos separadas** para entidades y municipios. Cuando e
324
440
  fitToIds={["09", "15", "14"]}
325
441
  jenksK={5}
326
442
 
327
- // Popup se adapta automáticamente:
328
- // - En entidades: solo muestra nombre (sin datos)
329
- // - En municipios: muestra nombre + datos del CSV municipal
443
+ // Popup adaptativo
330
444
  enablePopup={true}
331
445
  popupDataLabel="Habitantes"
332
446
  popupDataField="poblacion"
@@ -334,71 +448,196 @@ Puedes usar **fuentes de datos separadas** para entidades y municipios. Cuando e
334
448
  ```
335
449
 
336
450
  **Comportamiento del popup con CSV dual:**
337
- - **Vista de entidades**: Solo muestra el nombre (ej: "Ciudad de México") sin datos adicionales
338
- - **Vista de municipios** (después del click): Muestra nombre del municipio + valor del CSV municipal (ej: "Azcapotzalco - Habitantes: 385,000")
451
+ - **Vista de entidades**: Solo muestra el nombre (sin datos adicionales)
452
+ - **Vista de municipios**: Muestra nombre + valor del CSV municipal
339
453
 
340
454
  ---
341
455
 
342
- ## TotalesDisplay
456
+ ## Modos de Estilo
343
457
 
344
- Componente para mostrar totales y estadísticas de manera flexible y responsive. Soporta datos hardcodeados, desde CSV o una combinación de ambos.
458
+ ### Modo Boolean
345
459
 
346
- ### Características
460
+ Pinta las geometrías en dos colores según el valor.
347
461
 
348
- - **Tres formas de uso**: Datos hardcodeados, CSV por URL o CSV desde archivo local
349
- - **Responsive**: Se adapta automáticamente a desktop, tablet y mobile
350
- - **Centrado por defecto**: Posicionamiento centrado configurable
351
- - **Personalizable**: Formateadores custom para labels y valores
352
- - **TypeScript**: Completamente tipado
462
+ **Colores por defecto:**
463
+ - `value === 1` `#66827f` (verde azulado)
464
+ - `value === 0 / null / undefined` → `#f3f3f3` (gris claro)
353
465
 
354
- ### Uso Básico
466
+ **Con colores personalizados:**
467
+ ```tsx
468
+ <MapaPMTiles
469
+ mode="boolean"
470
+ color={['#e3f2fd', '#1976d2']} // [colorFalse, colorTrue]
471
+ />
472
+ ```
473
+
474
+ **Sin colores personalizados:**
475
+ ```tsx
476
+ <MapaPMTiles mode="boolean" />
477
+ ```
478
+
479
+ ---
355
480
 
356
- #### Importar el componente
481
+ ### Modo Jenks
482
+
483
+ Clasifica los valores numéricos usando el algoritmo Jenks Natural Breaks.
484
+
485
+ **Colores por defecto:**
486
+ - De `#f3f3f3` (gris claro) a `#66827f` (verde azulado)
487
+ - Número de clases controlado por `jenksK` (default: 5)
357
488
 
489
+ **Con rampa automática:**
358
490
  ```tsx
359
- import { TotalesDisplay } from '@atdt/geo-ui';
360
- import '@atdt/geo-ui/style.css';
491
+ <MapaPMTiles
492
+ mode="jenks"
493
+ jenksK={5}
494
+ color={['#fff3e0', '#e65100']} // [colorMin, colorMax]
495
+ />
361
496
  ```
362
497
 
363
- #### Ejemplo 1: Datos hardcodeados (más simple)
498
+ **Con colores exactos:**
499
+ ```tsx
500
+ <MapaPMTiles
501
+ mode="jenks"
502
+ jenksK={4}
503
+ color={['#fff9c4', '#ffeb3b', '#fbc02d', '#f57f17']} // 4 colores
504
+ />
505
+ ```
364
506
 
507
+ **Sin colores personalizados:**
365
508
  ```tsx
366
- import { TotalesDisplay } from '@atdt/geo-ui';
509
+ <MapaPMTiles mode="jenks" jenksK={7} />
510
+ ```
367
511
 
368
- function App() {
369
- return (
370
- <TotalesDisplay
371
- items={[
372
- { label: "Total de caminos abiertos", value: 496 },
373
- { label: "Total de caminos cerrados", value: 9 },
374
- ]}
375
- />
376
- );
377
- }
512
+ ---
513
+
514
+ ## Props de MapaPMTiles
515
+
516
+ ### Props Obligatorias
517
+
518
+ | Prop | Tipo | Descripción |
519
+ |------|------|-------------|
520
+ | `csvUrl` o `csvFile` | `string \| File` | URL del CSV remoto o archivo File local |
521
+
522
+ ### Props de Datos
523
+
524
+ | Prop | Tipo | Default | Descripción |
525
+ |------|------|---------|-------------|
526
+ | `pmtilesUrl` | `string` | URL de entidades de México | URL del archivo PMTiles remoto |
527
+ | `sourceLayer` | `string` | `"entidad"` | Nombre de la capa vectorial en el PMTiles |
528
+ | `joinGeomKey` | `string` | `"cvegeo"` | Campo de la geometría para el join |
529
+ | `joinCsvKey` | `string` | `joinGeomKey` | Campo del CSV para el join |
530
+ | `field` | `string` | `"valor"` | Campo del CSV con los valores a visualizar |
531
+
532
+ ### Props de Visualización
533
+
534
+ | Prop | Tipo | Default | Descripción |
535
+ |------|------|---------|-------------|
536
+ | `mode` | `"boolean" \| "jenks"` | `"boolean"` | Modo de estilo |
537
+ | `jenksK` | `number` | `5` | Número de clases para Jenks |
538
+ | `color` | `[string, string] \| string[]` | `['#f3f3f3', '#66827f']` | **v1.12.1**: Colores personalizados. Boolean: `[colorFalse, colorTrue]`. Jenks: `[colorMin, colorMax]` o array exacto |
539
+ | `width` | `string \| number` | `"100%"` | Ancho del mapa |
540
+ | `height` | `string \| number` | `520` | Alto del mapa (px si es número) |
541
+
542
+ ### Props de Navegación
543
+
544
+ | Prop | Tipo | Default | Descripción |
545
+ |------|------|---------|-------------|
546
+ | `initialView` | `object` | `{center: [-102, 23], zoom: 4}` | Vista inicial (ignorado si hay `fitToIds`) |
547
+ | `initialView.center` | `[number, number]` | `[-102, 23]` | Centro inicial [lng, lat] |
548
+ | `initialView.zoom` | `number` | `4` | Zoom inicial |
549
+ | `fitToIds` | `string \| string[]` | `undefined` | IDs de features para filtrar y zoom automático |
550
+ | `bboxField` | `string` | `"bbox"` | Campo con bbox precalculado |
551
+
552
+ ### Props de Municipios
553
+
554
+ | Prop | Tipo | Default | Descripción |
555
+ |------|------|---------|-------------|
556
+ | `showMunicipios` | `boolean` | `false` | Activa modo municipal |
557
+ | `csvUrlMunicipios` | `string` | `undefined` | URL del CSV para municipios |
558
+ | `csvFileMunicipios` | `File` | `undefined` | Archivo File para municipios |
559
+ | `joinCsvKeyMunicipios` | `string` | `"cvegeo"` | Campo del CSV municipal para join |
560
+ | `fieldMunicipios` | `string` | `field` | Campo del CSV municipal a visualizar |
561
+ | `modeMunicipios` | `"boolean" \| "jenks"` | `mode` | Modo de estilo para municipios |
562
+ | `colorMunicipios` | `[string, string] \| string[]` | `color` | **v1.12.1**: Colores para municipios |
563
+
564
+ ### Props de Interactividad
565
+
566
+ | Prop | Tipo | Default | Descripción |
567
+ |------|------|---------|-------------|
568
+ | `enablePopup` | `boolean` | `false` | Habilita popup con hover |
569
+ | `popupDataLabel` | `string` | `undefined` | Etiqueta para el dato del popup |
570
+ | `popupDataField` | `string` | `undefined` | Campo del CSV para el popup |
571
+ | `onFeatureClick` | `(id: string, props: any) => void` | `undefined` | Callback al hacer click (solo con 2+ entidades) |
572
+
573
+ ---
574
+
575
+ ## Formato CSV
576
+
577
+ El archivo CSV debe tener:
578
+
579
+ - **Header row** con nombres de columnas
580
+ - Una columna con el **join key** que coincida con `joinGeomKey`
581
+ - Una columna con los **valores** especificada en `field`
582
+
583
+ **Ejemplo:**
584
+
585
+ ```csv
586
+ cvegeo,nombre,valor
587
+ 01,Aguascalientes,1
588
+ 02,Baja California,0
589
+ 09,Ciudad de México,1
378
590
  ```
379
591
 
380
- #### Ejemplo 2: Datos desde CSV (URL)
592
+ ---
593
+
594
+ # TotalesDisplay
595
+
596
+ Componente para mostrar totales y estadísticas de manera flexible y responsive.
597
+
598
+ ## Características
599
+
600
+ - **Tres formas de uso**: Datos hardcodeados, CSV por URL o archivo local
601
+ - **Responsive**: Se adapta a desktop, tablet y mobile
602
+ - **Centrado por defecto**: Posicionamiento configurable
603
+ - **Personalizable**: Formateadores custom para labels y valores
604
+ - **TypeScript**: Completamente tipado
605
+
606
+ ## Uso Básico
607
+
608
+ ### Importar
381
609
 
382
610
  ```tsx
383
- import { TotalesDisplay } from '@atdt/geo-ui';
611
+ import { TotalesDisplay } from '@datosgeo-atdt/geo-ui';
612
+ import '@datosgeo-atdt/geo-ui/style.css';
613
+ ```
384
614
 
385
- function App() {
386
- return (
387
- <TotalesDisplay
388
- csvUrl="https://example.com/datos.csv"
389
- joinCsvKey="tipo"
390
- field="cantidad"
391
- labelFormatter={(key) => `Total de ${key.toLowerCase()}`}
392
- valueFormatter={(value) => value.toLocaleString('es-MX')}
393
- />
394
- );
395
- }
615
+ ### Datos hardcodeados
616
+
617
+ ```tsx
618
+ <TotalesDisplay
619
+ items={[
620
+ { label: "Total de caminos abiertos", value: 496 },
621
+ { label: "Total de caminos cerrados", value: 9 },
622
+ ]}
623
+ />
624
+ ```
625
+
626
+ ### Datos desde CSV (URL)
627
+
628
+ ```tsx
629
+ <TotalesDisplay
630
+ csvUrl="https://example.com/datos.csv"
631
+ joinCsvKey="tipo"
632
+ field="cantidad"
633
+ labelFormatter={(key) => `Total de ${key.toLowerCase()}`}
634
+ valueFormatter={(value) => value.toLocaleString('es-MX')}
635
+ />
396
636
  ```
397
637
 
398
- #### Ejemplo 3: Datos desde archivo local
638
+ ### Datos desde archivo local
399
639
 
400
640
  ```tsx
401
- import { TotalesDisplay } from '@atdt/geo-ui';
402
641
  import { useState } from 'react';
403
642
 
404
643
  function App() {
@@ -424,10 +663,9 @@ function App() {
424
663
  }
425
664
  ```
426
665
 
427
- #### Ejemplo 4: Con filtro específico
666
+ ### Con filtro específico
428
667
 
429
668
  ```tsx
430
- // Mostrar solo un elemento específico del CSV
431
669
  <TotalesDisplay
432
670
  csvUrl="https://example.com/datos.csv"
433
671
  joinCsvKey="region"
@@ -438,46 +676,54 @@ function App() {
438
676
  />
439
677
  ```
440
678
 
441
- #### Ejemplo 5: Sin centrado
679
+ ### Integrando con MapaPMTiles
442
680
 
443
681
  ```tsx
444
- <TotalesDisplay
445
- items={[
446
- { label: "Cobertura total", value: "98%" },
447
- { label: "Usuarios activos", value: 15234 },
448
- ]}
449
- centered={false}
450
- />
682
+ <div>
683
+ <TotalesDisplay
684
+ items={[
685
+ { label: "Total de caminos abiertos", value: 496 },
686
+ { label: "Total de caminos cerrados", value: 9 },
687
+ ]}
688
+ />
689
+
690
+ <MapaPMTiles
691
+ csvUrl="https://example.com/datos.csv"
692
+ fitToIds={["09", "15", "14"]}
693
+ mode="jenks"
694
+ enablePopup={true}
695
+ />
696
+ </div>
451
697
  ```
452
698
 
453
- ### Props de TotalesDisplay
699
+ ## Props de TotalesDisplay
454
700
 
455
- #### Props de Datos (una de estas opciones es requerida)
701
+ ### Props de Datos (una es requerida)
456
702
 
457
703
  | Prop | Tipo | Descripción |
458
704
  |------|------|-------------|
459
- | `items` | `TotalItem[]` | Array de objetos con `label` y `value` para mostrar datos hardcodeados |
705
+ | `items` | `TotalItem[]` | Array de objetos con `label` y `value` |
460
706
  | `csvUrl` | `string` | URL del CSV remoto |
461
707
  | `csvFile` | `File` | Archivo File local |
462
708
 
463
- #### Props de Configuración CSV
709
+ ### Props de Configuración CSV
464
710
 
465
711
  | Prop | Tipo | Default | Descripción |
466
712
  |------|------|---------|-------------|
467
- | `joinCsvKey` | `string` | `"key"` | Campo del CSV para usar como identificador |
468
- | `field` | `string` | `"valor"` | Campo del CSV con los valores a visualizar |
469
- | `filterKey` | `string` | `undefined` | Si se especifica, solo muestra el elemento con este key |
713
+ | `joinCsvKey` | `string` | `"key"` | Campo del CSV como identificador |
714
+ | `field` | `string` | `"valor"` | Campo del CSV con valores |
715
+ | `filterKey` | `string` | `undefined` | Mostrar solo este key |
470
716
 
471
- #### Props de Visualización
717
+ ### Props de Visualización
472
718
 
473
719
  | Prop | Tipo | Default | Descripción |
474
720
  |------|------|---------|-------------|
475
- | `centered` | `boolean` | `true` | Si el contenedor debe estar centrado |
476
- | `className` | `string` | `""` | Clases CSS adicionales para el contenedor |
477
- | `labelFormatter` | `(key: string, value: any) => string` | `undefined` | Función para formatear el label |
478
- | `valueFormatter` | `(value: any) => string \| number` | `undefined` | Función para formatear el valor |
721
+ | `centered` | `boolean` | `true` | Contenedor centrado |
722
+ | `className` | `string` | `""` | Clases CSS adicionales |
723
+ | `labelFormatter` | `(key: string, value: any) => string` | `undefined` | Formatear label |
724
+ | `valueFormatter` | `(value: any) => string \| number` | `undefined` | Formatear valor |
479
725
 
480
- #### Tipo TotalItem
726
+ ### Tipo TotalItem
481
727
 
482
728
  ```tsx
483
729
  interface TotalItem {
@@ -486,392 +732,120 @@ interface TotalItem {
486
732
  }
487
733
  ```
488
734
 
489
- ### Ejemplos Completos
490
-
491
- #### Ejemplo con datos dinámicos según estado del mapa
492
-
493
- ```tsx
494
- import { TotalesDisplay } from '@atdt/geo-ui';
495
- import { useState } from 'react';
496
-
497
- function App() {
498
- const [selectedRegion, setSelectedRegion] = useState<string | null>(null);
499
-
500
- const datosGlobales = [
501
- { label: "Total nacional de escuelas", value: 12450 },
502
- { label: "Total nacional de estudiantes", value: 850000 },
503
- ];
504
-
505
- return (
506
- <div>
507
- {!selectedRegion && (
508
- <TotalesDisplay items={datosGlobales} />
509
- )}
510
-
511
- {selectedRegion && (
512
- <TotalesDisplay
513
- csvUrl="https://example.com/datos-regionales.csv"
514
- filterKey={selectedRegion}
515
- joinCsvKey="region"
516
- field="total"
517
- labelFormatter={(key, value) => `${key} - Total`}
518
- valueFormatter={(value) => value.toLocaleString('es-MX')}
519
- />
520
- )}
521
- </div>
522
- );
523
- }
524
- ```
525
-
526
- #### Ejemplo integrando con MapaPMTiles
527
-
528
- ```tsx
529
- import { MapaPMTiles, TotalesDisplay } from '@atdt/geo-ui';
530
- import '@atdt/geo-ui/style.css';
735
+ ## Responsive
531
736
 
532
- function App() {
533
- return (
534
- <div>
535
- <TotalesDisplay
536
- items={[
537
- { label: "Total de caminos abiertos", value: 496 },
538
- { label: "Total de caminos cerrados", value: 9 },
539
- ]}
540
- />
541
-
542
- <MapaPMTiles
543
- csvUrl="https://example.com/datos.csv"
544
- fitToIds={["09", "15", "14"]}
545
- mode="jenks"
546
- enablePopup={true}
547
- />
548
- </div>
549
- );
550
- }
551
- ```
552
-
553
- ### Responsive
554
-
555
- El componente se adapta automáticamente:
556
-
557
- - **Desktop**: Layout horizontal con espaciado amplio (13.89vw entre items)
558
- - **Tablet** (601px - 1024px): Espaciado medio (8vw entre items)
559
- - **Mobile** (≤600px): Layout vertical, centrado, con espaciado vertical entre items
560
-
561
- ### Personalización Avanzada
562
-
563
- ```tsx
564
- <TotalesDisplay
565
- csvUrl="https://example.com/estadisticas.csv"
566
- joinCsvKey="categoria"
567
- field="valor"
568
- centered={true}
569
- className="mis-totales-custom"
570
- labelFormatter={(key, value) => {
571
- // Lógica custom para el label
572
- if (key === 'total') return `🏆 Total General`;
573
- return `📊 ${key.charAt(0).toUpperCase() + key.slice(1)}`;
574
- }}
575
- valueFormatter={(value) => {
576
- // Formatear números con separadores de miles
577
- if (typeof value === 'number') {
578
- return `${value.toLocaleString('es-MX')} unidades`;
579
- }
580
- return value;
581
- }}
582
- />
583
- ```
584
-
585
- ### Estilos CSS Personalizados
586
-
587
- Puedes sobrescribir los estilos usando tu propio CSS:
588
-
589
- ```css
590
- .mis-totales-custom {
591
- background-color: #f0f0f0;
592
- padding: 20px;
593
- border-radius: 8px;
594
- }
595
-
596
- .mis-totales-custom .totales-item {
597
- font-size: 1.2em;
598
- color: #2c3e50;
599
- }
600
-
601
- .mis-totales-custom .totales-value {
602
- color: #66827f;
603
- font-weight: 900;
604
- }
605
- ```
737
+ - **Desktop**: Layout horizontal con espaciado amplio (13.89vw)
738
+ - **Tablet** (601px - 1024px): Espaciado medio (8vw)
739
+ - **Mobile** (≤600px): Layout vertical centrado
606
740
 
607
741
  ---
608
742
 
609
- ## DataTable
743
+ # DataTable
610
744
 
611
- Componente de tabla genérico y flexible para mostrar datos tabulares con soporte para carga automática de CSV desde la carpeta `public`.
745
+ Componente de tabla genérico y flexible con soporte para carga automática de CSV.
612
746
 
613
- ### Características
747
+ ## Características
614
748
 
615
- - **Carga automática de CSV**: Lee archivos CSV desde la carpeta `public` y parsea los datos
616
- - **Detección automática de columnas**: Extrae los nombres de las columnas directamente del CSV
617
- - **Columnas personalizables**: Define qué columnas mostrar y su ancho
618
- - **Tamaño ajustable**: Props `width` y `height` para controlar dimensiones
619
- - **Formato automático de números**: Formatea números con separadores de miles (estilo mexicano)
620
- - **Índice opcional**: Puede mostrar numeración de filas
621
- - **Responsive**: Se adapta automáticamente a móvil
622
- - **Estados de carga**: Muestra "Cargando datos..." mientras procesa el CSV
623
- - **Manejo de errores**: Muestra mensajes descriptivos si falla la carga
624
- - **TypeScript**: Completamente tipado
749
+ - **Carga automática de CSV**: Lee archivos desde `public/`
750
+ - **Detección automática de columnas**: Extrae nombres del CSV
751
+ - **Columnas personalizables**: Define qué mostrar y anchos
752
+ - **Formato automático**: Números con separadores de miles
753
+ - **Índice opcional**: Numeración de filas
754
+ - **Responsive**: Se adapta a móvil
755
+ - **Interactividad**: Callback `onRowClick`
625
756
 
626
- ### Uso Básico
757
+ ## Uso Básico
627
758
 
628
- #### Importar el componente
759
+ ### Importar
629
760
 
630
761
  ```tsx
631
- import { DataTable } from '@atdt/geo-ui';
632
- import '@atdt/geo-ui/style.css';
762
+ import { DataTable } from '@datosgeo-atdt/geo-ui';
763
+ import '@datosgeo-atdt/geo-ui/style.css';
633
764
  ```
634
765
 
635
- #### Ejemplo 1: Cargar CSV automáticamente desde public/
766
+ ### Cargar CSV desde public/
636
767
 
637
- Si tienes un archivo `alcaldias.csv` en la carpeta `public/` de tu proyecto:
768
+ Si tienes `public/alcaldias.csv`:
638
769
 
639
770
  ```csv
640
771
  alcaldia,poblacion
641
772
  Iztapalapa,1815786
642
773
  Gustavo A. Madero,1185772
643
774
  Álvaro Obregón,749982
644
- Tlalpan,677104
645
- ```
646
-
647
- Simplemente especifica la ruta del archivo:
648
-
649
- ```tsx
650
- import { DataTable } from '@atdt/geo-ui';
651
-
652
- function App() {
653
- return (
654
- <DataTable csvPath="/alcaldias.csv" />
655
- );
656
- }
657
775
  ```
658
776
 
659
- **El componente automáticamente:**
660
- - Carga el CSV desde `public/alcaldias.csv`
661
- - Detecta los nombres de las columnas (`alcaldia`, `poblacion`)
662
- - Los usa como headers de la tabla
663
- - Parsea los datos y los muestra
664
- - Formatea números con separadores de miles (1,815,786)
665
- - Distribuye las columnas equitativamente (50% cada una en este caso)
666
-
667
- #### Ejemplo 2: Personalizar nombres de columnas
668
-
669
- Puedes sobrescribir los nombres de las columnas del CSV:
777
+ Simplemente:
670
778
 
671
779
  ```tsx
672
- import { DataTable } from '@atdt/geo-ui';
673
-
674
- function App() {
675
- return (
676
- <DataTable
677
- csvPath="/alcaldias.csv"
678
- columns={[
679
- { key: 'alcaldia', label: 'Alcaldía', width: '60%' },
680
- { key: 'poblacion', label: 'Población Total', width: '40%' }
681
- ]}
682
- showIndex={true}
683
- indexLabel="#"
684
- />
685
- );
686
- }
780
+ <DataTable csvPath="/alcaldias.csv" />
687
781
  ```
688
782
 
689
- #### Ejemplo 3: Datos directos (sin CSV)
690
-
691
- También puedes pasar datos directamente sin cargar un CSV:
692
-
693
- ```tsx
694
- import { DataTable } from '@atdt/geo-ui';
695
-
696
- function App() {
697
- const datos = [
698
- { nombre: 'Ciudad de México', habitantes: 9209944 },
699
- { nombre: 'Guadalajara', habitantes: 1495189 },
700
- { nombre: 'Monterrey', habitantes: 1142994 }
701
- ];
702
-
703
- return (
704
- <DataTable
705
- data={datos}
706
- columns={[
707
- { key: 'nombre', label: 'Ciudad' },
708
- { key: 'habitantes', label: 'Habitantes' }
709
- ]}
710
- />
711
- );
712
- }
713
- ```
783
+ **Auto-detecta:**
784
+ - Nombres de columnas (`alcaldia`, `poblacion`)
785
+ - Parsea datos y formatea números (1,815,786)
786
+ - Distribuye columnas equitativamente (50% cada una)
714
787
 
715
- #### Ejemplo 4: Múltiples columnas con distribución automática
788
+ ### Personalizar columnas
716
789
 
717
790
  ```tsx
718
- // Con 4 columnas, cada una ocupa automáticamente 25% del ancho
719
791
  <DataTable
720
- csvPath="/productos.csv"
792
+ csvPath="/alcaldias.csv"
721
793
  columns={[
722
- { key: 'nombre', label: 'Producto' },
723
- { key: 'categoria', label: 'Categoría' },
724
- { key: 'precio', label: 'Precio' },
725
- { key: 'stock', label: 'Stock' }
794
+ { key: 'alcaldia', label: 'Alcaldía', width: '60%' },
795
+ { key: 'poblacion', label: 'Población Total', width: '40%' }
726
796
  ]}
727
797
  showIndex={true}
798
+ indexLabel="#"
728
799
  />
729
800
  ```
730
801
 
731
- #### Ejemplo 5: Control manual de anchos de columnas
802
+ ### Datos directos (sin CSV)
732
803
 
733
804
  ```tsx
734
- // Especifica anchos personalizados cuando necesites distribución no equitativa
805
+ const datos = [
806
+ { nombre: 'Ciudad de México', habitantes: 9209944 },
807
+ { nombre: 'Guadalajara', habitantes: 1495189 },
808
+ { nombre: 'Monterrey', habitantes: 1142994 }
809
+ ];
810
+
735
811
  <DataTable
736
- csvPath="/datos.csv"
812
+ data={datos}
737
813
  columns={[
738
- { key: 'nombre', label: 'Nombre', width: '50%' },
739
- { key: 'valor1', label: 'Valor 1', width: '25%' },
740
- { key: 'valor2', label: 'Valor 2', width: '25%' }
814
+ { key: 'nombre', label: 'Ciudad' },
815
+ { key: 'habitantes', label: 'Habitantes' }
741
816
  ]}
742
817
  />
743
818
  ```
744
819
 
745
- ### Props de DataTable
746
-
747
- #### Props de Datos (al menos una opción es requerida)
748
-
749
- | Prop | Tipo | Descripción |
750
- |------|------|-------------|
751
- | `data` | `Record<string, any>[]` | Array de objetos con los datos a mostrar |
752
- | `csvPath` | `string` | Ruta del archivo CSV en la carpeta `public` (ej: `/datos.csv`) |
753
-
754
- #### Props de Configuración
755
-
756
- | Prop | Tipo | Default | Descripción |
757
- |------|------|---------|-------------|
758
- | `columns` | `DataTableColumn[]` | Auto-detectado | Definición de columnas a mostrar |
759
- | `width` | `string` | Controlado por CSS | Ancho del contenedor (por defecto 50% del viewport en desktop, 100% en móvil) |
760
- | `height` | `string` | Controlado por CSS | Alto del contenedor (por defecto 100% con scroll interno cuando excede 70vh) |
761
- | `className` | `string` | `""` | Clases CSS adicionales |
762
- | `showIndex` | `boolean` | `false` | Mostrar columna con índice numérico |
763
- | `indexLabel` | `string` | `"#"` | Etiqueta para la columna de índice |
764
- | `onRowClick` | `(row: Record<string, any>, index: number) => void` | `undefined` | Callback que se ejecuta al hacer click en una fila. Recibe los datos de la fila y su índice |
820
+ ### Integración con MapaPMTiles
765
821
 
766
- #### Tipo DataTableColumn
822
+ Layout dashboard con mapa y tabla:
767
823
 
768
824
  ```tsx
769
- interface DataTableColumn {
770
- key: string; // Campo del objeto/CSV
771
- label: string; // Texto a mostrar en el header
772
- width?: string; // Ancho de la columna (ej: "40%", "200px")
773
- }
774
- ```
775
-
776
- ### Ejemplos Completos
777
-
778
- #### Ejemplo con CSV de productos
825
+ <div style={{ display: 'flex', width: '100%', height: '100vh' }}>
826
+ {/* Mapa 50% */}
827
+ <MapaPMTiles
828
+ csvUrl="/datos_entidades.csv"
829
+ fitToIds={["09", "15", "14"]}
830
+ mode="jenks"
831
+ enablePopup={true}
832
+ />
779
833
 
780
- ```tsx
781
- import { DataTable } from '@atdt/geo-ui';
782
-
783
- // public/productos.csv
784
- // nombre,categoria,precio,stock
785
- // Laptop Dell,Electrónica,15999,50
786
- // Mouse Logitech,Accesorios,299,150
787
- // Monitor Samsung,Electrónica,4599,30
788
-
789
- function App() {
790
- return (
791
- <DataTable
792
- csvPath="/productos.csv"
793
- columns={[
794
- { key: 'nombre', label: 'Producto', width: '30%' },
795
- { key: 'categoria', label: 'Categoría', width: '25%' },
796
- { key: 'precio', label: 'Precio', width: '25%' },
797
- { key: 'stock', label: 'Stock', width: '20%' }
798
- ]}
799
- width="900px"
800
- height="500px"
801
- showIndex={true}
802
- />
803
- );
804
- }
834
+ {/* Tabla 50% */}
835
+ <DataTable
836
+ csvPath="/datos_entidades.csv"
837
+ columns={[
838
+ { key: 'entidad', label: 'Entidad' },
839
+ { key: 'valor', label: 'Valor' }
840
+ ]}
841
+ />
842
+ </div>
805
843
  ```
806
844
 
807
- #### Ejemplo con datos dinámicos
845
+ ### Interactividad bidireccional (Tabla ↔ Mapa)
808
846
 
809
847
  ```tsx
810
- import { DataTable } from '@atdt/geo-ui';
811
- import { useState, useEffect } from 'react';
812
-
813
- function App() {
814
- const [datos, setDatos] = useState([]);
815
-
816
- useEffect(() => {
817
- // Cargar datos desde una API
818
- fetch('https://api.example.com/estadisticas')
819
- .then(res => res.json())
820
- .then(data => setDatos(data));
821
- }, []);
822
-
823
- return (
824
- <DataTable
825
- data={datos}
826
- columns={[
827
- { key: 'region', label: 'Región' },
828
- { key: 'total', label: 'Total' }
829
- ]}
830
- />
831
- );
832
- }
833
- ```
834
-
835
- #### Ejemplo integrando con MapaPMTiles
836
-
837
- Layout tipo dashboard con mapa y tabla lado a lado:
838
-
839
- ```tsx
840
- import { MapaPMTiles, DataTable } from '@atdt/geo-ui';
841
- import '@atdt/geo-ui/style.css';
842
-
843
- function App() {
844
- return (
845
- <div style={{ display: 'flex', width: '100%', height: '100vh' }}>
846
- {/* Mapa ocupa 50% */}
847
- <MapaPMTiles
848
- csvPath="/datos_entidades.csv"
849
- fitToIds={["09", "15", "14"]}
850
- mode="jenks"
851
- enablePopup={true}
852
- />
853
-
854
- {/* DataTable ocupa 50% automáticamente */}
855
- <DataTable
856
- csvPath="/datos_entidades.csv"
857
- columns={[
858
- { key: 'entidad', label: 'Entidad' },
859
- { key: 'valor', label: 'Valor' }
860
- ]}
861
- />
862
- </div>
863
- );
864
- }
865
- ```
866
-
867
- #### Ejemplo con interactividad bidireccional (Tabla ↔ Mapa)
868
-
869
- Crea interacción completa entre la tabla y el mapa usando `onRowClick` y `onFeatureClick`:
870
-
871
- ```tsx
872
- import { MapaPMTiles, DataTable } from '@atdt/geo-ui';
873
848
  import { useState } from 'react';
874
- import '@atdt/geo-ui/style.css';
875
849
 
876
850
  function App() {
877
851
  const [nivel, setNivel] = useState<'entidad' | 'municipio'>('entidad');
@@ -881,13 +855,12 @@ function App() {
881
855
  <div style={{ display: 'flex', width: '100%', height: '100vh' }}>
882
856
  {/* Mapa con click handler */}
883
857
  <MapaPMTiles
884
- csvPath={nivel === 'entidad' ? '/prueba_entidad.csv' : `/cdmx_prueba.csv`}
858
+ csvUrl={nivel === 'entidad' ? '/entidades.csv' : '/municipios.csv'}
885
859
  fitToIds={selectedEnt ? [selectedEnt] : undefined}
886
860
  mode="jenks"
887
861
  showMunicipios={nivel === 'municipio'}
888
862
  enablePopup={true}
889
- onFeatureClick={(featureId, properties) => {
890
- // Click en mapa → cambia tabla a municipios de esa entidad
863
+ onFeatureClick={(featureId) => {
891
864
  if (nivel === 'entidad') {
892
865
  setSelectedEnt(featureId);
893
866
  setNivel('municipio');
@@ -897,20 +870,8 @@ function App() {
897
870
 
898
871
  {/* Tabla con click handler */}
899
872
  <DataTable
900
- csvPath={nivel === 'entidad' ? '/prueba_entidad.csv' : `/cdmx_prueba.csv`}
901
- columns={
902
- nivel === 'entidad'
903
- ? [
904
- { key: 'entidad', label: 'Entidad' },
905
- { key: 'total', label: 'Total' }
906
- ]
907
- : [
908
- { key: 'municipio', label: 'Municipio' },
909
- { key: 'valor', label: 'Valor' }
910
- ]
911
- }
873
+ csvPath={nivel === 'entidad' ? '/entidades.csv' : '/municipios.csv'}
912
874
  onRowClick={(row) => {
913
- // Click en tabla → hace zoom en mapa a esa entidad
914
875
  if (nivel === 'entidad') {
915
876
  setSelectedEnt(row.cvegeo);
916
877
  setNivel('municipio');
@@ -920,20 +881,8 @@ function App() {
920
881
 
921
882
  {/* Botón para regresar */}
922
883
  {nivel === 'municipio' && (
923
- <button
924
- style={{
925
- position: 'absolute',
926
- top: 20,
927
- left: 20,
928
- zIndex: 1000,
929
- padding: '10px 20px'
930
- }}
931
- onClick={() => {
932
- setNivel('entidad');
933
- setSelectedEnt(null);
934
- }}
935
- >
936
- ← Regresar a entidades
884
+ <button onClick={() => { setNivel('entidad'); setSelectedEnt(null); }}>
885
+ ← Regresar
937
886
  </button>
938
887
  )}
939
888
  </div>
@@ -941,184 +890,38 @@ function App() {
941
890
  }
942
891
  ```
943
892
 
944
- **Flujo de interacción bidireccional:**
945
- 1. **Vista inicial**: Muestra tabla con entidades (`prueba_entidad.csv`) y mapa de México
946
- 2. **Click en MAPA**: Hace zoom a la entidad y cambia tabla a municipios
947
- 3. **Click en TABLA**: Hace zoom en el mapa y cambia tabla a municipios
948
- 4. **Mapa hace zoom**: Automáticamente hacia la entidad seleccionada
949
- 5. **Tabla cambia**: Muestra datos municipales (`cdmx_prueba.csv`)
950
- 6. **Botón "Regresar"**: Vuelve a la vista de entidades
951
-
952
- ### Formato de Números
953
-
954
- Los números se formatean automáticamente con separadores de miles usando el formato mexicano:
955
-
956
- - `1815786` → `1,815,786`
957
- - `9209944` → `9,209,944`
958
- - `150` → `150`
959
-
960
- ### Estados de Carga
961
-
962
- El componente muestra diferentes estados:
963
-
964
- 1. **Cargando**: "Cargando datos..." mientras lee el CSV
965
- 2. **Error**: Mensaje de error en rojo si falla la carga
966
- 3. **Vacío**: "No hay datos para mostrar" si el CSV está vacío
967
- 4. **Datos**: Tabla renderizada con los datos
968
-
969
- ### Diseño y Layout
893
+ ## Props de DataTable
970
894
 
971
- El componente está diseñado para integrarse con layouts tipo dashboard:
972
-
973
- - **Desktop**:
974
- - Ocupa **50% del ancho** del contenedor padre por defecto
975
- - Centrado vertical y horizontal
976
- - Scroll interno cuando el contenido excede **70vh**
977
- - Headers y celdas con tamaño `1.11vw`
978
- - Columnas se distribuyen automáticamente usando flexbox
979
-
980
- - **Mobile** (≤600px):
981
- - Ocupa **100% del ancho**
982
- - Headers con tamaño `3.5vw`
983
- - Celdas con tamaño `4vw`
984
- - Padding ajustado para pantallas pequeñas
985
- - Box shadow más pronunciado
986
-
987
- ### Personalización de Estilos
988
-
989
- Puedes sobrescribir los estilos usando la clase `className`:
990
-
991
- ```tsx
992
- <DataTable
993
- csvPath="/datos.csv"
994
- className="mi-tabla-custom"
995
- />
996
- ```
997
-
998
- ```css
999
- .mi-tabla-custom {
1000
- border: 2px solid #66827f;
1001
- box-shadow: 0 4px 8px rgba(0,0,0,0.2);
1002
- }
1003
-
1004
- .mi-tabla-custom .tableHeader {
1005
- background-color: #66827f;
1006
- color: white;
1007
- }
1008
- ```
1009
-
1010
- ---
1011
-
1012
- ## Props de MapaPMTiles
1013
-
1014
- ### Props Obligatorias
895
+ ### Props de Datos (una es requerida)
1015
896
 
1016
897
  | Prop | Tipo | Descripción |
1017
898
  |------|------|-------------|
1018
- | `csvUrl` o `csvFile` | `string \| File` | URL del CSV remoto o archivo File local. **Al menos uno debe estar presente** |
899
+ | `data` | `Record<string, any>[]` | Array de objetos |
900
+ | `csvPath` | `string` | Ruta del CSV en `public/` |
1019
901
 
1020
- ### Props Opcionales
902
+ ### Props de Configuración
1021
903
 
1022
904
  | Prop | Tipo | Default | Descripción |
1023
905
  |------|------|---------|-------------|
1024
- | `pmtilesUrl` | `string` | `"https://www.datosgeoespaciales.atdt.gob.mx/datalake/pmtiles/componente/entidad.pmtiles"` | URL del archivo PMTiles remoto. **Por defecto usa el PMTiles de entidades de México** |
1025
- | `sourceLayer` | `string` | `"entidad"` | Nombre de la capa vectorial dentro del PMTiles |
1026
- | `joinGeomKey` | `string` | `"cvegeo"` | Campo de la geometría para hacer el join (también usado como `promoteId`) |
1027
- | `joinCsvKey` | `string` | `joinGeomKey` | Campo del CSV para hacer el join |
1028
- | `field` | `string` | `"valor"` | Campo del CSV con los valores a visualizar |
1029
- | `mode` | `"boolean" \| "jenks"` | `"boolean"` | Modo de estilo: booleano o clasificación Jenks |
1030
- | `width` | `string \| number` | `"100%"` | Ancho del mapa |
1031
- | `height` | `string \| number` | `520` | Alto del mapa (en px si es número) |
1032
- | `initialView` | `object` | `{center: [-102, 23], zoom: 4}` | Vista inicial del mapa (ignorado si se usa `fitToIds`) |
1033
- | `initialView.center` | `[number, number]` | `[-102, 23]` | Centro inicial [lng, lat] |
1034
- | `initialView.zoom` | `number` | `4` | Zoom inicial |
1035
- | `fitToIds` | `string \| string[]` | `undefined` | ID o array de IDs de features para filtrar y hacer zoom automático (sin animación) |
1036
- | `bboxField` | `string` | `"bbox"` | Campo con bbox precalculado en PMTiles |
1037
- | `jenksK` | `number` | `5` | Número de clases para clasificación Jenks |
1038
- | `showMunicipios` | `boolean` | `false` | Activa modo municipal: muestra municipios con datos temáticos y entidad como contorno |
1039
- | `enablePopup` | `boolean` | `false` | Habilita popup con hover para mostrar información |
1040
- | `popupDataLabel` | `string` | `undefined` | Etiqueta para el dato adicional del popup (ej: "Población total") |
1041
- | `popupDataField` | `string` | `undefined` | Campo del CSV para mostrar en el popup (usa el valor de `field` si no se especifica) |
1042
- | `csvUrlMunicipios` | `string` | `undefined` | URL del CSV remoto para municipios (usado cuando hay drill-down interactivo) |
1043
- | `csvFileMunicipios` | `File` | `undefined` | Archivo File local para municipios (usado cuando hay drill-down interactivo) |
1044
- | `joinCsvKeyMunicipios` | `string` | `"cvegeo"` | Campo del CSV municipal para hacer el join (por defecto usa cvegeo de 5 dígitos) |
1045
- | `fieldMunicipios` | `string` | `field` | Campo del CSV municipal con los valores a visualizar (por defecto usa el mismo `field` de entidades) |
1046
- | `modeMunicipios` | `"boolean" \| "jenks"` | `mode` | Modo de estilo para municipios (permite usar diferente clasificación que entidades) |
1047
- | `onFeatureClick` | `(featureId: string, properties: any) => void` | `undefined` | Callback que se ejecuta al hacer click en una feature del mapa. Recibe el ID de la feature y sus propiedades. Solo funciona cuando hay 2 o más entidades en `fitToIds` |
1048
-
1049
- ## Modos de Estilo
1050
-
1051
- ### Modo Boolean
1052
-
1053
- Pinta las geometrías en dos colores según el valor:
1054
-
1055
- - `value === 1` → **#66827f** (verde azulado)
1056
- - `value === 0 / null / undefined` → **#f3f3f3** (gris claro)
1057
-
1058
- ```tsx
1059
- <MapaPMTiles
1060
- mode="boolean"
1061
- {...otherProps}
1062
- />
1063
- ```
1064
-
1065
- ### Modo Jenks
1066
-
1067
- Clasifica los valores numéricos usando el algoritmo Jenks Natural Breaks y aplica una rampa de colores:
906
+ | `columns` | `DataTableColumn[]` | Auto-detectado | Definición de columnas |
907
+ | `width` | `string` | Por CSS | Ancho del contenedor (50% desktop, 100% mobile) |
908
+ | `height` | `string` | Por CSS | Alto del contenedor (scroll si > 70vh) |
909
+ | `className` | `string` | `""` | Clases CSS adicionales |
910
+ | `showIndex` | `boolean` | `false` | Mostrar índice numérico |
911
+ | `indexLabel` | `string` | `"#"` | Etiqueta para índice |
912
+ | `onRowClick` | `(row: Record<string, any>, index: number) => void` | `undefined` | Callback al hacer click en fila |
1068
913
 
1069
- - De **#f3f3f3** (gris claro) a **#66827f** (verde azulado)
1070
- - Número de clases controlado por `jenksK` (default: 5)
914
+ ### Tipo DataTableColumn
1071
915
 
1072
916
  ```tsx
1073
- <MapaPMTiles
1074
- mode="jenks"
1075
- jenksK={7}
1076
- {...otherProps}
1077
- />
1078
- ```
1079
-
1080
- ## Formato CSV
1081
-
1082
- El archivo CSV debe tener:
1083
-
1084
- - **Header row** con nombres de columnas
1085
- - Una columna con el **join key** que coincida con el campo `joinGeomKey` de las geometrías
1086
- - Una columna con los **valores** especificada en `field`
1087
-
1088
- Ejemplo:
1089
-
1090
- ```csv
1091
- CVE_ENT,nombre,valor
1092
- 01,Aguascalientes,1
1093
- 02,Baja California,0
1094
- 09,Ciudad de México,1
917
+ interface DataTableColumn {
918
+ key: string; // Campo del objeto/CSV
919
+ label: string; // Texto del header
920
+ width?: string; // Ancho de columna (ej: "40%", "200px")
921
+ }
1095
922
  ```
1096
923
 
1097
- ## Interactividad del Mapa
1098
-
1099
- El componente tiene **interactividad desactivada** por defecto para mantener un estilo estático:
1100
-
1101
- - `boxZoom`: false
1102
- - `doubleClickZoom`: false
1103
- - `dragRotate`: false
1104
- - `keyboard`: false
1105
- - `scrollZoom`: false
1106
- - `touchPitch`: false
1107
- - `dragPan`: false
1108
- - `touchZoomRotate`: true (permitido)
1109
-
1110
- ## Notas CORS
1111
-
1112
- Para consumir PMTiles y CSV de dominios externos, asegúrate de que:
1113
-
1114
- 1. El servidor tenga configurado CORS adecuadamente
1115
- 2. Para PMTiles, el servidor debe soportar **Range requests** (HTTP 206)
1116
- 3. Headers necesarios:
1117
- ```
1118
- Access-Control-Allow-Origin: *
1119
- Access-Control-Allow-Headers: Range
1120
- Accept-Ranges: bytes
1121
- ```
924
+ ---
1122
925
 
1123
926
  ## Tecnologías
1124
927
 
@@ -1129,14 +932,35 @@ Para consumir PMTiles y CSV de dominios externos, asegúrate de que:
1129
932
  - **PapaParse**: Parsing de CSV
1130
933
  - **Vite**: Build tool
1131
934
 
935
+ ---
936
+
1132
937
  ## Licencia
1133
938
 
1134
939
  ISC
1135
940
 
941
+ ---
942
+
1136
943
  ## Autor
1137
944
 
1138
945
  Dirección de Datos Geográficos - ATDT
1139
946
 
947
+ ---
948
+
1140
949
  ## Contribuciones
1141
950
 
1142
951
  Issues y pull requests son bienvenidos en [GitLab](https://gitlab.com/atdt-desarrollogeo/componentes).
952
+
953
+ ---
954
+
955
+ ## Notas CORS
956
+
957
+ Para consumir PMTiles y CSV de dominios externos:
958
+
959
+ 1. El servidor debe tener CORS configurado
960
+ 2. Para PMTiles, debe soportar **Range requests** (HTTP 206)
961
+ 3. Headers necesarios:
962
+ ```
963
+ Access-Control-Allow-Origin: *
964
+ Access-Control-Allow-Headers: Range
965
+ Accept-Ranges: bytes
966
+ ```