multinom_mapa 1.1.0 → 1.1.1
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 +379 -379
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,379 +1,379 @@
|
|
|
1
|
-
# multinom_mapa
|
|
2
|
-
|
|
3
|
-
Web Component `<multinom-mapa>`: mapa de los 2,457 municipios de México coloreado por un KPI de 0 a 100 o por cantidades, con vista nacional por entidad, detalle por municipio, panel de resumen y búsqueda por coordenada. Incluye además **código postal y colonia** de las 32 entidades, que solo entran al build de tu app si las importas.
|
|
4
|
-
|
|
5
|
-
No depende de ningún framework. Funciona en **cualquier versión de Angular** (y en React, Vue o HTML plano), porque el navegador lo trata como una etiqueta nativa.
|
|
6
|
-
|
|
7
|
-
- Modo `kpi` (por omisión): el valor de cada entidad (y el nacional) es el promedio de sus municipios **ponderado por población 2020**. Valores fuera de 0–100 se recortan; vacíos o no numéricos cuentan como "sin dato".
|
|
8
|
-
- Modo `conteo`: cantidades (obras, quejas, visitas…) con escala de 0 al máximo visible; entidad y nacional son la **suma**.
|
|
9
|
-
- La geometría (~2.9 MB) se carga **diferida**, una sola vez por página, y no entra a tu bundle principal.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Instalación
|
|
14
|
-
|
|
15
|
-
El paquete es público en npmjs.com como **`multinom_mapa`**. La etiqueta HTML que registra es `<multinom-mapa>`. Se instala como cualquier otra librería, sin sesión ni token:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm install multinom_mapa
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Uso en Angular
|
|
24
|
-
|
|
25
|
-
### 1. Registrar el elemento
|
|
26
|
-
|
|
27
|
-
Importa el paquete una vez, en `main.ts`:
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
import 'multinom_mapa';
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### 2. Permitir la etiqueta en las plantillas
|
|
34
|
-
|
|
35
|
-
**Componentes standalone** (Angular 15+):
|
|
36
|
-
|
|
37
|
-
```ts
|
|
38
|
-
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
39
|
-
|
|
40
|
-
@Component({
|
|
41
|
-
selector: 'app-tablero',
|
|
42
|
-
standalone: true,
|
|
43
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
44
|
-
templateUrl: './tablero.component.html',
|
|
45
|
-
})
|
|
46
|
-
export class TableroComponent {}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
**Con NgModule** (cualquier versión):
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
53
|
-
|
|
54
|
-
@NgModule({
|
|
55
|
-
// ...
|
|
56
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
57
|
-
})
|
|
58
|
-
export class AppModule {}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### 3. Usarlo
|
|
62
|
-
|
|
63
|
-
```html
|
|
64
|
-
<multinom-mapa
|
|
65
|
-
titulo="Satisfacción por municipio"
|
|
66
|
-
nombre-kpi="Satisfacción"
|
|
67
|
-
[kpi]="valores"
|
|
68
|
-
(seleccion)="alSeleccionar($event)"
|
|
69
|
-
(nivel-cambio)="alCambiarNivel($event)">
|
|
70
|
-
</multinom-mapa>
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
import type { DetalleSeleccion, DetalleNivel } from 'multinom_mapa';
|
|
75
|
-
|
|
76
|
-
export class TableroComponent {
|
|
77
|
-
valores: Record<string, number> = { '22014': 78.5, '22011': 41 };
|
|
78
|
-
|
|
79
|
-
alSeleccionar(e: Event) {
|
|
80
|
-
const d = (e as CustomEvent<DetalleSeleccion | null>).detail;
|
|
81
|
-
console.log(d?.municipio, d?.kpi);
|
|
82
|
-
}
|
|
83
|
-
alCambiarNivel(e: Event) {
|
|
84
|
-
const d = (e as CustomEvent<DetalleNivel>).detail;
|
|
85
|
-
console.log(d.nivel, d.entidad);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Cada vez que asignes un objeto nuevo a `valores`, el mapa se actualiza. Puedes pasarle datos antes de que termine de cargar la geometría: los guarda y los aplica al terminar.
|
|
91
|
-
|
|
92
|
-
### Llamar métodos desde el componente
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
import { ElementRef, ViewChild } from '@angular/core';
|
|
96
|
-
import type { MapaKpi } from 'multinom_mapa';
|
|
97
|
-
|
|
98
|
-
@ViewChild('mapa') mapa!: ElementRef<MapaKpi>;
|
|
99
|
-
|
|
100
|
-
async ubicarOficina() {
|
|
101
|
-
await this.mapa.nativeElement.listo;
|
|
102
|
-
const r = this.mapa.nativeElement.localizar(20.5888, -100.3899);
|
|
103
|
-
// r = { cve_ent: '22', cve_geo: '22014', entidad: 'Querétaro', municipio: 'Querétaro', kpi: 78.5 }
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
```html
|
|
108
|
-
<multinom-mapa #mapa></multinom-mapa>
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### SSR (Angular Universal / `@angular/ssr`)
|
|
112
|
-
|
|
113
|
-
Importar el paquete en el servidor no truena: el elemento solo se registra en el navegador. En el servidor la etiqueta queda vacía y se dibuja al hidratar.
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## Códigos postales y colonias
|
|
118
|
-
|
|
119
|
-
Vienen en el mismo paquete (`npm install multinom_mapa`, una sola instalación). Lo que decide si entran al build de tu app es **qué importas** en `main.ts`:
|
|
120
|
-
|
|
121
|
-
```ts
|
|
122
|
-
import 'multinom_mapa'; // estados y municipios (siempre)
|
|
123
|
-
import 'multinom_mapa/qro'; // + CP y colonias de Querétaro
|
|
124
|
-
import 'multinom_mapa/jal'; // + CP y colonias de Jalisco
|
|
125
|
-
import 'multinom_mapa/todo'; // + CP y colonias de las 32 entidades
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
Con solo `import 'multinom_mapa'` el build queda igual que sin CP ni colonias. Con una entidad importada, la geometría de cada municipio va en su propio chunk y **solo se descarga cuando se abre ese municipio**: si usas `raiz="22011"`, el navegador descarga únicamente El Marqués. Con `multinom_mapa/todo` el build genera un chunk por municipio (unos 2,450 archivos en `dist/` de tu app), pero el navegador sigue descargando solo los que se abren.
|
|
129
|
-
|
|
130
|
-
Abreviaturas: `ags` `bc` `bcs` `camp` `coah` `col` `chis` `chih` `cdmx` `dgo` `gto` `gro` `hgo` `jal` `mex` `mich` `mor` `nay` `nl` `oax` `pue` `qro` `qroo` `slp` `sin` `son` `tab` `tamps` `tlax` `ver` `yuc` `zac`.
|
|
131
|
-
|
|
132
|
-
### Navegación: `raiz` y `niveles`
|
|
133
|
-
|
|
134
|
-
México (1) → entidad: sus municipios (2) → municipio: sus CP o colonias (3) → CP: sus colonias (4).
|
|
135
|
-
|
|
136
|
-
- `raiz` fija dónde empieza; el usuario no puede subir más arriba.
|
|
137
|
-
- `niveles` fija hasta dónde puede bajar (1–4, por omisión 4). Al llegar al último nivel, el clic selecciona en lugar de abrir.
|
|
138
|
-
|
|
139
|
-
```html
|
|
140
|
-
<multinom-mapa niveles="2"></multinom-mapa> <!-- México → municipios, sin CP ni colonias -->
|
|
141
|
-
<multinom-mapa raiz="22" niveles="2"></multinom-mapa> <!-- Querétaro y sus municipios -->
|
|
142
|
-
<multinom-mapa raiz="22"></multinom-mapa> <!-- Querétaro → municipio → CP → colonia -->
|
|
143
|
-
<multinom-mapa raiz="22011" niveles="3"></multinom-mapa> <!-- El Marqués por CP o colonias, sin abrir cada CP -->
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Los niveles 3 y 4 además requieren haber importado la entidad (`multinom_mapa/qro`); si no, el mapa se queda en municipios. Si `raiz` es un municipio, `niveles` nunca baja de 3.
|
|
147
|
-
|
|
148
|
-
Dentro del municipio hay un selector **CP / Colonias** (atributo `capa-municipio` para el valor inicial). Con colonias se ve todo el municipio de una vez.
|
|
149
|
-
|
|
150
|
-
### Ejemplo: obras públicas en El Marqués
|
|
151
|
-
|
|
152
|
-
```html
|
|
153
|
-
<multinom-mapa
|
|
154
|
-
raiz="22011" modo="conteo" capa-municipio="colonias"
|
|
155
|
-
titulo="Obras públicas" nombre-kpi="Obras"
|
|
156
|
-
[kpi]="obrasPorMunicipio"
|
|
157
|
-
[kpiCp]="obrasPorCp"
|
|
158
|
-
[kpiColonias]="obrasPorColonia"
|
|
159
|
-
(seleccion)="alSeleccionar($event)">
|
|
160
|
-
</multinom-mapa>
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
```ts
|
|
164
|
-
obrasPorMunicipio = { '22011': 47 };
|
|
165
|
-
obrasPorCp = { '76246': 12, '76240': 5 };
|
|
166
|
-
obrasPorColonia = { '2201100010001': 3 }; // cvegeo de INEGI (13 dígitos)
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
Cada nivel muestra **los valores que le pases a ese nivel**; el mapa no los suma de colonias a CP ni de CP a municipio, porque un CP puede cruzar municipios y no todas las colonias están delimitadas. Lo único que agrega es entidad y nacional a partir de municipios. En modo `conteo`, lo que no venga en los datos de un nivel cuenta como 0.
|
|
170
|
-
|
|
171
|
-
### Qué hay que saber de los datos
|
|
172
|
-
|
|
173
|
-
- **CP:** polígonos de SEPOMEX, recortados con el límite de cada municipio. Si un CP cruza dos municipios, aparece en ambos (el tooltip dice "También en…").
|
|
174
|
-
- **Colonias:** *Delimitación de colonias y otros asentamientos humanos 2025* de INEGI. **No cubre todo el país**: cada municipio entrega la suya, y muchos municipios rurales no tienen ninguna (ahí se ven solo los CP). En Querétaro, por ejemplo, faltan Querétaro capital, San Juan del Río, Colón, Huimilpan y Amealco, y El Marqués tiene 137 colonias (faltan fraccionamientos como Zibatá). Las zonas sin colonia se ven en gris.
|
|
175
|
-
- La clave de colonia es el `cvegeo` de INEGI (entidad + municipio + localidad + asentamiento). El CP del atributo de INEGI no siempre coincide con el polígono de SEPOMEX; cada colonia se dibuja dentro del CP donde cae, y el tooltip muestra ambos si difieren.
|
|
176
|
-
|
|
177
|
-
### Regenerar los datos (desarrollo)
|
|
178
|
-
|
|
179
|
-
1. Fuentes en `build/fuentes/` (no se versionan; ~1.4 GB). El script las busca en cualquier subcarpeta:
|
|
180
|
-
- SEPOMEX, "Códigos postales por entidad federativa" (datos.gob.mx) → carpetas `CP_<Abrev>` (p. ej. `CP/CP_Qro`).
|
|
181
|
-
- INEGI, [Delimitación de colonias y otros asentamientos humanos](https://www.inegi.org.mx/programas/dcah/) → carpetas `<ee>_<nombre>` (p. ej. `DCAH/22_queretaro`).
|
|
182
|
-
2. `npm run region -- 22` (una entidad) o `npm run region -- todas` (las 32; agrega `--forzar` para rehacer las que ya existen) → `build/regiones/<ee>.json` (estos sí se versionan).
|
|
183
|
-
3. `npm run build` → genera `dist/regiones/<abrev>/` y `dist/regiones/todo.js`.
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
## Referencia
|
|
188
|
-
|
|
189
|
-
### Atributos
|
|
190
|
-
|
|
191
|
-
| Atributo | Valor | Qué hace |
|
|
192
|
-
|---|---|---|
|
|
193
|
-
| `titulo` | texto | Título del encabezado. Por omisión "KPI municipal de México". |
|
|
194
|
-
| `nombre-kpi` | texto | Nombre del indicador en la leyenda. Por omisión "KPI". |
|
|
195
|
-
| `tema` | `auto` · `claro` · `oscuro` | `auto` (por omisión) sigue el modo del sistema. |
|
|
196
|
-
| `sin-encabezado` | — | Oculta el encabezado. La atribución de las fuentes pasa a la leyenda. |
|
|
197
|
-
| `sin-panel` | — | Oculta el panel lateral: queda solo el mapa. |
|
|
198
|
-
| `sin-localizar` | — | Oculta la tarjeta "Localizar coordenada". |
|
|
199
|
-
| `con-carga` | — | Muestra la tarjeta para generar datos aleatorios o cargar un CSV/JSON a mano. |
|
|
200
|
-
| `demo` | semilla opcional | Arranca con datos aleatorios reproducibles. |
|
|
201
|
-
| `datos-url` | URL | Descarga la geometría desde un JSON en lugar del módulo diferido (ver abajo). |
|
|
202
|
-
| `modo` | `kpi` · `conteo` | `kpi` (por omisión): 0–100, semáforo, promedio ponderado. `conteo`: cantidades, escala secuencial, suma. |
|
|
203
|
-
| `raiz` | clave de entidad o municipio | Dónde empieza la navegación (`22`, `22011`). Sin él, en México. |
|
|
204
|
-
| `niveles` | `1` · `2` · `3` · `4` | Hasta dónde se puede bajar: entidades, municipios, CP/colonias del municipio, colonias del CP. Por omisión `4`. |
|
|
205
|
-
| `capa-municipio` | `cp` · `colonias` | Cómo se ve un municipio abierto (requiere importar la entidad). Por omisión `cp`. |
|
|
206
|
-
|
|
207
|
-
### Propiedades
|
|
208
|
-
|
|
209
|
-
| Propiedad | Tipo | |
|
|
210
|
-
|---|---|---|
|
|
211
|
-
| `kpi` | `Record<string, number>` o arreglo de filas | Leer o asignar los valores por municipio. |
|
|
212
|
-
| `kpiCp` | igual | Valores por código postal. |
|
|
213
|
-
| `kpiColonias` | igual | Valores por colonia (`cvegeo` de 13 dígitos). |
|
|
214
|
-
| `modo` | `'kpi' \| 'conteo'` | Solo lectura (refleja el atributo). |
|
|
215
|
-
| `niveles` | `1 \| 2 \| 3 \| 4` | Refleja el atributo `niveles`. |
|
|
216
|
-
| `colorear` | `boolean` | `false` pinta todo en gris. |
|
|
217
|
-
| `listo` | `Promise<void>` | Se resuelve cuando el mapa está dibujado. |
|
|
218
|
-
|
|
219
|
-
### Métodos
|
|
220
|
-
|
|
221
|
-
| Método | Devuelve |
|
|
222
|
-
|---|---|
|
|
223
|
-
| `setKpi(datos, opciones?)` | `{ cargados, ignoradas }`, o `null` si aún carga (se aplica al terminar). `opciones`: texto de origen o `{ nivel: 'municipio' \| 'cp' \| 'colonia', origen }`. |
|
|
224
|
-
| `getKpi(nivel?)` | Valores de un nivel (municipio por omisión). |
|
|
225
|
-
| `kpiEntidades()` | Valor por entidad (`cve_ent` → valor o `null`). |
|
|
226
|
-
| `kpiNacional()` | Valor nacional (ponderado o suma, según el modo). |
|
|
227
|
-
| `abrirEntidad(cve_ent)` | Muestra los municipios de una entidad. |
|
|
228
|
-
| `abrirMunicipio(cve_geo)` | `Promise`. Abre el municipio con sus CP y colonias (sin la entidad importada o con `niveles` < 3, abre la entidad y lo selecciona). |
|
|
229
|
-
| `abrirCp(cp, cve_geo?)` | `Promise`. Abre un CP y muestra sus colonias (con `niveles="3"`, solo lo selecciona). |
|
|
230
|
-
| `seleccionar(cve_geo)` | Abre la entidad y selecciona el municipio. |
|
|
231
|
-
| `seleccionarColonia(cvegeo)` | `Promise`. Abre municipio y CP de la colonia y la selecciona. |
|
|
232
|
-
| `subir()` | Sube un nivel, sin pasar de `raiz`. También con la tecla Escape. |
|
|
233
|
-
| `nacional()` | Vuelve a la vista nacional (o a la raíz). |
|
|
234
|
-
| `localizar(lat, lon, mover = true)` | `{ cve_ent, cve_geo, entidad, municipio, kpi }` y, si la geometría del municipio ya está cargada, `cp`, `kpi_cp`, `cve_col`, `colonia`, `kpi_colonia`. Con `mover`, navega y marca el punto. |
|
|
235
|
-
| `localizarDetalle(lat, lon, mover = true)` | `Promise` con lo mismo, cargando antes la geometría de CP/colonias. |
|
|
236
|
-
| `aleatorio(semilla?, huecos?)` | Genera datos de prueba (también para CP y colonias de las entidades importadas). |
|
|
237
|
-
| `encuadrarVista()` | Reencuadra la vista actual. |
|
|
238
|
-
| `redibujar()` | Vuelve a leer los colores CSS y redibuja. |
|
|
239
|
-
|
|
240
|
-
### Formatos aceptados por `kpi` / `setKpi`
|
|
241
|
-
|
|
242
|
-
```js
|
|
243
|
-
{ "22014": 78.5, "22011": 41 } // objeto clave → valor
|
|
244
|
-
[{ cve_geo: "22014", kpi: 78.5 }, { cve: 22011, valor: 41 }] // filas (cve_geo|cve|clave|cp|cvegeo, kpi|valor|value)
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
Las claves se rellenan con ceros a la izquierda (`1001` → `01001`). Para leer un CSV ya tienes `leerCsv(texto)` exportado por el paquete.
|
|
248
|
-
|
|
249
|
-
### Eventos
|
|
250
|
-
|
|
251
|
-
Todos son `CustomEvent`, burbujean y salen del Shadow DOM.
|
|
252
|
-
|
|
253
|
-
| Evento | `detail` |
|
|
254
|
-
|---|---|
|
|
255
|
-
| `mapa-listo` | — |
|
|
256
|
-
| `mapa-error` | `{ error }` (no se pudo cargar la geometría) |
|
|
257
|
-
| `kpi-cambio` | `{ cargados, ignoradas, origen, nivel }` |
|
|
258
|
-
| `seleccion` | `{ tipo: 'municipio' \| 'cp' \| 'colonia', clave, nombre, cve_geo, cve_ent, municipio, entidad, kpi, poblacion }` (+ `cp`, `cve_col`, `colonia`, `tipo_asentamiento` según el tipo), o `null` al deseleccionar |
|
|
259
|
-
| `nivel-cambio` | `{ nivel: 'nacional' \| 'entidad' \| 'municipio' \| 'cp', cve_ent, entidad, cve_geo, municipio, cp }` |
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Estilos
|
|
264
|
-
|
|
265
|
-
El componente toma la **tipografía de tu página**. Necesita una altura: por omisión mide 640 px.
|
|
266
|
-
|
|
267
|
-
```css
|
|
268
|
-
multinom-mapa {
|
|
269
|
-
height: calc(100vh - 64px);
|
|
270
|
-
--mk-accent: #c2185b; /* color de selección y enlaces */
|
|
271
|
-
--mk-bg: transparent; /* fondo detrás de las tarjetas */
|
|
272
|
-
--mk-relleno: 0; /* margen interno */
|
|
273
|
-
}
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
Variables disponibles: `--mk-bg`, `--mk-panel`, `--mk-ink`, `--mk-ink2`, `--mk-muted`, `--mk-line`, `--mk-land`, `--mk-edge`, `--mk-accent`, `--mk-nodata`, `--mk-hatch`, `--mk-halo`, `--mk-mono`, `--mk-relleno`. Si las cambias en caliente, llama a `redibujar()` para que el canvas las tome.
|
|
277
|
-
|
|
278
|
-
Partes para `::part()`: `app`, `encabezado`, `mapa`, `leyenda`, `panel`.
|
|
279
|
-
|
|
280
|
-
Por debajo de 760 px **de ancho del componente** (no de la ventana), el panel pasa debajo del mapa.
|
|
281
|
-
|
|
282
|
-
---
|
|
283
|
-
|
|
284
|
-
## La geometría
|
|
285
|
-
|
|
286
|
-
Por omisión el componente hace `import('./datos.js')` del propio paquete; tu bundler (Angular CLI con webpack o esbuild, Vite, etc.) lo separa en su propio chunk y solo se descarga cuando aparece el primer mapa. No hay que configurar nada.
|
|
287
|
-
|
|
288
|
-
Si prefieres servirla como archivo estático (por ejemplo, desde un CDN), copia el JSON a tus assets en `angular.json`:
|
|
289
|
-
|
|
290
|
-
```json
|
|
291
|
-
"assets": [
|
|
292
|
-
{ "glob": "mexico.json", "input": "node_modules/multinom_mapa/dist", "output": "assets/multinom-mapa" }
|
|
293
|
-
]
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
y apúntalo con el atributo o de forma global:
|
|
297
|
-
|
|
298
|
-
```html
|
|
299
|
-
<multinom-mapa datos-url="assets/multinom-mapa/mexico.json"></multinom-mapa>
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
```ts
|
|
303
|
-
import { configurarDatosUrl } from 'multinom_mapa';
|
|
304
|
-
configurarDatosUrl('assets/multinom-mapa/mexico.json');
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
---
|
|
308
|
-
|
|
309
|
-
## Otros entornos
|
|
310
|
-
|
|
311
|
-
**HTML plano**
|
|
312
|
-
|
|
313
|
-
```html
|
|
314
|
-
<script type="module">import 'https://cdn.jsdelivr.net/npm/multinom_mapa@1/dist/index.js';</script>
|
|
315
|
-
<multinom-mapa demo></multinom-mapa>
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
**React 19+** pasa propiedades y eventos a custom elements de forma nativa:
|
|
319
|
-
`<multinom-mapa kpi={valores} onseleccion={e => …} />`.
|
|
320
|
-
|
|
321
|
-
---
|
|
322
|
-
|
|
323
|
-
## Desarrollo y publicación
|
|
324
|
-
|
|
325
|
-
El código fuente vive en el repo de GitHub; npmjs.com solo recibe el paquete compilado.
|
|
326
|
-
|
|
327
|
-
```bash
|
|
328
|
-
npm install # instala dependencias y compila (script prepare)
|
|
329
|
-
npm run build # recompila dist/
|
|
330
|
-
npm pack # opcional: genera el .tgz para revisarlo antes de publicar
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Primera publicación (una sola vez, desde tu computadora)
|
|
334
|
-
|
|
335
|
-
Trusted Publishing solo se puede configurar en un paquete que ya existe, así que la primera versión se publica a mano:
|
|
336
|
-
|
|
337
|
-
```bash
|
|
338
|
-
npm login # cuenta de npmjs.com con 2FA
|
|
339
|
-
npm publish # compila (script prepare) y sube multinom_mapa@<versión de package.json>
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
Luego, en npmjs.com → paquete `multinom_mapa` → *Settings* → *Trusted Publisher* → **GitHub Actions**:
|
|
343
|
-
|
|
344
|
-
| Campo | Valor |
|
|
345
|
-
|---|---|
|
|
346
|
-
| Organization or user | `MULTIEVAL` |
|
|
347
|
-
| Repository | `multinom_mapa` |
|
|
348
|
-
| Workflow filename | `publicar.yml` |
|
|
349
|
-
| Environment | (vacío) |
|
|
350
|
-
|
|
351
|
-
Con eso GitHub Actions publica sin token guardado (npm verifica la identidad del flujo con OIDC). Opcional y recomendado: en el mismo *Settings* → *Publishing access*, exige 2FA y deshabilita los tokens, para que solo se pueda publicar desde el flujo o con tu 2FA.
|
|
352
|
-
|
|
353
|
-
### Publicar una versión nueva
|
|
354
|
-
|
|
355
|
-
La publicación es automática con GitHub Actions (`.github/workflows/publicar.yml`): se dispara al subir una etiqueta `v*`.
|
|
356
|
-
|
|
357
|
-
```bash
|
|
358
|
-
npm version minor # 1.1.0 → 1.2.0: cambia package.json, hace commit y crea la etiqueta v1.2.0
|
|
359
|
-
git push --follow-tags # sube el commit y la etiqueta; Actions publica en npm
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
Usa `patch` para correcciones (1.1.1), `minor` para funciones nuevas compatibles (1.2.0) y `major` si rompes algo de la API (2.0.0). El flujo se detiene si la etiqueta no coincide con la versión de `package.json`.
|
|
363
|
-
|
|
364
|
-
En los proyectos Angular actualizas con `npm install multinom_mapa@latest` (o la versión que quieras).
|
|
365
|
-
|
|
366
|
-
### Dueños del paquete
|
|
367
|
-
|
|
368
|
-
El paquete queda a nombre de la cuenta que lo publica primero. Para pasarlo a otra cuenta u organización, sin cambiar el nombre ni los `import` de los proyectos:
|
|
369
|
-
|
|
370
|
-
- **Otra cuenta como dueña:** `npm owner add <usuario> multinom_mapa` (todos los dueños tienen los mismos permisos; luego `npm owner rm <usuario>` para quitar la anterior).
|
|
371
|
-
- **Una organización de npm:** en npmjs.com → paquete → *Settings* → transferir a la organización; los permisos se manejan después por equipos.
|
|
372
|
-
|
|
373
|
-
### Visibilidad
|
|
374
|
-
|
|
375
|
-
`multinom_mapa` es un nombre **sin scope**, y en npm esos paquetes siempre son públicos. Si algún día necesitaras uno privado, tendría que publicarse con otro nombre que lleve scope (por ejemplo `@tu-org/multinom_mapa`) y cambiar el `import` en los proyectos.
|
|
376
|
-
|
|
377
|
-
## Licencia
|
|
378
|
-
|
|
379
|
-
El código es [MIT](./LICENSE), © MULTIEVAL. Los datos geográficos y estadísticos tienen licencias propias (geoBoundaries ODbL, INEGI términos de libre uso, SEPOMEX CC BY 4.0); en conjunto se distribuyen bajo ODbL. Ver [LICENCIA-DATOS.md](./LICENCIA-DATOS.md).
|
|
1
|
+
# multinom_mapa
|
|
2
|
+
|
|
3
|
+
Web Component `<multinom-mapa>`: mapa de los 2,457 municipios de México coloreado por un KPI de 0 a 100 o por cantidades, con vista nacional por entidad, detalle por municipio, panel de resumen y búsqueda por coordenada. Incluye además **código postal y colonia** de las 32 entidades, que solo entran al build de tu app si las importas.
|
|
4
|
+
|
|
5
|
+
No depende de ningún framework. Funciona en **cualquier versión de Angular** (y en React, Vue o HTML plano), porque el navegador lo trata como una etiqueta nativa.
|
|
6
|
+
|
|
7
|
+
- Modo `kpi` (por omisión): el valor de cada entidad (y el nacional) es el promedio de sus municipios **ponderado por población 2020**. Valores fuera de 0–100 se recortan; vacíos o no numéricos cuentan como "sin dato".
|
|
8
|
+
- Modo `conteo`: cantidades (obras, quejas, visitas…) con escala de 0 al máximo visible; entidad y nacional son la **suma**.
|
|
9
|
+
- La geometría (~2.9 MB) se carga **diferida**, una sola vez por página, y no entra a tu bundle principal.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Instalación
|
|
14
|
+
|
|
15
|
+
El paquete es público en npmjs.com como **`multinom_mapa`**. La etiqueta HTML que registra es `<multinom-mapa>`. Se instala como cualquier otra librería, sin sesión ni token:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install multinom_mapa
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Uso en Angular
|
|
24
|
+
|
|
25
|
+
### 1. Registrar el elemento
|
|
26
|
+
|
|
27
|
+
Importa el paquete una vez, en `main.ts`:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import 'multinom_mapa';
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Permitir la etiqueta en las plantillas
|
|
34
|
+
|
|
35
|
+
**Componentes standalone** (Angular 15+):
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
39
|
+
|
|
40
|
+
@Component({
|
|
41
|
+
selector: 'app-tablero',
|
|
42
|
+
standalone: true,
|
|
43
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
44
|
+
templateUrl: './tablero.component.html',
|
|
45
|
+
})
|
|
46
|
+
export class TableroComponent {}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Con NgModule** (cualquier versión):
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
53
|
+
|
|
54
|
+
@NgModule({
|
|
55
|
+
// ...
|
|
56
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
57
|
+
})
|
|
58
|
+
export class AppModule {}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Usarlo
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<multinom-mapa
|
|
65
|
+
titulo="Satisfacción por municipio"
|
|
66
|
+
nombre-kpi="Satisfacción"
|
|
67
|
+
[kpi]="valores"
|
|
68
|
+
(seleccion)="alSeleccionar($event)"
|
|
69
|
+
(nivel-cambio)="alCambiarNivel($event)">
|
|
70
|
+
</multinom-mapa>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import type { DetalleSeleccion, DetalleNivel } from 'multinom_mapa';
|
|
75
|
+
|
|
76
|
+
export class TableroComponent {
|
|
77
|
+
valores: Record<string, number> = { '22014': 78.5, '22011': 41 };
|
|
78
|
+
|
|
79
|
+
alSeleccionar(e: Event) {
|
|
80
|
+
const d = (e as CustomEvent<DetalleSeleccion | null>).detail;
|
|
81
|
+
console.log(d?.municipio, d?.kpi);
|
|
82
|
+
}
|
|
83
|
+
alCambiarNivel(e: Event) {
|
|
84
|
+
const d = (e as CustomEvent<DetalleNivel>).detail;
|
|
85
|
+
console.log(d.nivel, d.entidad);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Cada vez que asignes un objeto nuevo a `valores`, el mapa se actualiza. Puedes pasarle datos antes de que termine de cargar la geometría: los guarda y los aplica al terminar.
|
|
91
|
+
|
|
92
|
+
### Llamar métodos desde el componente
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { ElementRef, ViewChild } from '@angular/core';
|
|
96
|
+
import type { MapaKpi } from 'multinom_mapa';
|
|
97
|
+
|
|
98
|
+
@ViewChild('mapa') mapa!: ElementRef<MapaKpi>;
|
|
99
|
+
|
|
100
|
+
async ubicarOficina() {
|
|
101
|
+
await this.mapa.nativeElement.listo;
|
|
102
|
+
const r = this.mapa.nativeElement.localizar(20.5888, -100.3899);
|
|
103
|
+
// r = { cve_ent: '22', cve_geo: '22014', entidad: 'Querétaro', municipio: 'Querétaro', kpi: 78.5 }
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```html
|
|
108
|
+
<multinom-mapa #mapa></multinom-mapa>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### SSR (Angular Universal / `@angular/ssr`)
|
|
112
|
+
|
|
113
|
+
Importar el paquete en el servidor no truena: el elemento solo se registra en el navegador. En el servidor la etiqueta queda vacía y se dibuja al hidratar.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Códigos postales y colonias
|
|
118
|
+
|
|
119
|
+
Vienen en el mismo paquete (`npm install multinom_mapa`, una sola instalación). Lo que decide si entran al build de tu app es **qué importas** en `main.ts`:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import 'multinom_mapa'; // estados y municipios (siempre)
|
|
123
|
+
import 'multinom_mapa/qro'; // + CP y colonias de Querétaro
|
|
124
|
+
import 'multinom_mapa/jal'; // + CP y colonias de Jalisco
|
|
125
|
+
import 'multinom_mapa/todo'; // + CP y colonias de las 32 entidades
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Con solo `import 'multinom_mapa'` el build queda igual que sin CP ni colonias. Con una entidad importada, la geometría de cada municipio va en su propio chunk y **solo se descarga cuando se abre ese municipio**: si usas `raiz="22011"`, el navegador descarga únicamente El Marqués. Con `multinom_mapa/todo` el build genera un chunk por municipio (unos 2,450 archivos en `dist/` de tu app), pero el navegador sigue descargando solo los que se abren.
|
|
129
|
+
|
|
130
|
+
Abreviaturas: `ags` `bc` `bcs` `camp` `coah` `col` `chis` `chih` `cdmx` `dgo` `gto` `gro` `hgo` `jal` `mex` `mich` `mor` `nay` `nl` `oax` `pue` `qro` `qroo` `slp` `sin` `son` `tab` `tamps` `tlax` `ver` `yuc` `zac`.
|
|
131
|
+
|
|
132
|
+
### Navegación: `raiz` y `niveles`
|
|
133
|
+
|
|
134
|
+
México (1) → entidad: sus municipios (2) → municipio: sus CP o colonias (3) → CP: sus colonias (4).
|
|
135
|
+
|
|
136
|
+
- `raiz` fija dónde empieza; el usuario no puede subir más arriba.
|
|
137
|
+
- `niveles` fija hasta dónde puede bajar (1–4, por omisión 4). Al llegar al último nivel, el clic selecciona en lugar de abrir.
|
|
138
|
+
|
|
139
|
+
```html
|
|
140
|
+
<multinom-mapa niveles="2"></multinom-mapa> <!-- México → municipios, sin CP ni colonias -->
|
|
141
|
+
<multinom-mapa raiz="22" niveles="2"></multinom-mapa> <!-- Querétaro y sus municipios -->
|
|
142
|
+
<multinom-mapa raiz="22"></multinom-mapa> <!-- Querétaro → municipio → CP → colonia -->
|
|
143
|
+
<multinom-mapa raiz="22011" niveles="3"></multinom-mapa> <!-- El Marqués por CP o colonias, sin abrir cada CP -->
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Los niveles 3 y 4 además requieren haber importado la entidad (`multinom_mapa/qro`); si no, el mapa se queda en municipios. Si `raiz` es un municipio, `niveles` nunca baja de 3.
|
|
147
|
+
|
|
148
|
+
Dentro del municipio hay un selector **CP / Colonias** (atributo `capa-municipio` para el valor inicial). Con colonias se ve todo el municipio de una vez.
|
|
149
|
+
|
|
150
|
+
### Ejemplo: obras públicas en El Marqués
|
|
151
|
+
|
|
152
|
+
```html
|
|
153
|
+
<multinom-mapa
|
|
154
|
+
raiz="22011" modo="conteo" capa-municipio="colonias"
|
|
155
|
+
titulo="Obras públicas" nombre-kpi="Obras"
|
|
156
|
+
[kpi]="obrasPorMunicipio"
|
|
157
|
+
[kpiCp]="obrasPorCp"
|
|
158
|
+
[kpiColonias]="obrasPorColonia"
|
|
159
|
+
(seleccion)="alSeleccionar($event)">
|
|
160
|
+
</multinom-mapa>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
obrasPorMunicipio = { '22011': 47 };
|
|
165
|
+
obrasPorCp = { '76246': 12, '76240': 5 };
|
|
166
|
+
obrasPorColonia = { '2201100010001': 3 }; // cvegeo de INEGI (13 dígitos)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Cada nivel muestra **los valores que le pases a ese nivel**; el mapa no los suma de colonias a CP ni de CP a municipio, porque un CP puede cruzar municipios y no todas las colonias están delimitadas. Lo único que agrega es entidad y nacional a partir de municipios. En modo `conteo`, lo que no venga en los datos de un nivel cuenta como 0.
|
|
170
|
+
|
|
171
|
+
### Qué hay que saber de los datos
|
|
172
|
+
|
|
173
|
+
- **CP:** polígonos de SEPOMEX, recortados con el límite de cada municipio. Si un CP cruza dos municipios, aparece en ambos (el tooltip dice "También en…").
|
|
174
|
+
- **Colonias:** *Delimitación de colonias y otros asentamientos humanos 2025* de INEGI. **No cubre todo el país**: cada municipio entrega la suya, y muchos municipios rurales no tienen ninguna (ahí se ven solo los CP). En Querétaro, por ejemplo, faltan Querétaro capital, San Juan del Río, Colón, Huimilpan y Amealco, y El Marqués tiene 137 colonias (faltan fraccionamientos como Zibatá). Las zonas sin colonia se ven en gris.
|
|
175
|
+
- La clave de colonia es el `cvegeo` de INEGI (entidad + municipio + localidad + asentamiento). El CP del atributo de INEGI no siempre coincide con el polígono de SEPOMEX; cada colonia se dibuja dentro del CP donde cae, y el tooltip muestra ambos si difieren.
|
|
176
|
+
|
|
177
|
+
### Regenerar los datos (desarrollo)
|
|
178
|
+
|
|
179
|
+
1. Fuentes en `build/fuentes/` (no se versionan; ~1.4 GB). El script las busca en cualquier subcarpeta:
|
|
180
|
+
- SEPOMEX, "Códigos postales por entidad federativa" (datos.gob.mx) → carpetas `CP_<Abrev>` (p. ej. `CP/CP_Qro`).
|
|
181
|
+
- INEGI, [Delimitación de colonias y otros asentamientos humanos](https://www.inegi.org.mx/programas/dcah/) → carpetas `<ee>_<nombre>` (p. ej. `DCAH/22_queretaro`).
|
|
182
|
+
2. `npm run region -- 22` (una entidad) o `npm run region -- todas` (las 32; agrega `--forzar` para rehacer las que ya existen) → `build/regiones/<ee>.json` (estos sí se versionan).
|
|
183
|
+
3. `npm run build` → genera `dist/regiones/<abrev>/` y `dist/regiones/todo.js`.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Referencia
|
|
188
|
+
|
|
189
|
+
### Atributos
|
|
190
|
+
|
|
191
|
+
| Atributo | Valor | Qué hace |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| `titulo` | texto | Título del encabezado. Por omisión "KPI municipal de México". |
|
|
194
|
+
| `nombre-kpi` | texto | Nombre del indicador en la leyenda. Por omisión "KPI". |
|
|
195
|
+
| `tema` | `auto` · `claro` · `oscuro` | `auto` (por omisión) sigue el modo del sistema. |
|
|
196
|
+
| `sin-encabezado` | — | Oculta el encabezado. La atribución de las fuentes pasa a la leyenda. |
|
|
197
|
+
| `sin-panel` | — | Oculta el panel lateral: queda solo el mapa. |
|
|
198
|
+
| `sin-localizar` | — | Oculta la tarjeta "Localizar coordenada". |
|
|
199
|
+
| `con-carga` | — | Muestra la tarjeta para generar datos aleatorios o cargar un CSV/JSON a mano. |
|
|
200
|
+
| `demo` | semilla opcional | Arranca con datos aleatorios reproducibles. |
|
|
201
|
+
| `datos-url` | URL | Descarga la geometría desde un JSON en lugar del módulo diferido (ver abajo). |
|
|
202
|
+
| `modo` | `kpi` · `conteo` | `kpi` (por omisión): 0–100, semáforo, promedio ponderado. `conteo`: cantidades, escala secuencial, suma. |
|
|
203
|
+
| `raiz` | clave de entidad o municipio | Dónde empieza la navegación (`22`, `22011`). Sin él, en México. |
|
|
204
|
+
| `niveles` | `1` · `2` · `3` · `4` | Hasta dónde se puede bajar: entidades, municipios, CP/colonias del municipio, colonias del CP. Por omisión `4`. |
|
|
205
|
+
| `capa-municipio` | `cp` · `colonias` | Cómo se ve un municipio abierto (requiere importar la entidad). Por omisión `cp`. |
|
|
206
|
+
|
|
207
|
+
### Propiedades
|
|
208
|
+
|
|
209
|
+
| Propiedad | Tipo | |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| `kpi` | `Record<string, number>` o arreglo de filas | Leer o asignar los valores por municipio. |
|
|
212
|
+
| `kpiCp` | igual | Valores por código postal. |
|
|
213
|
+
| `kpiColonias` | igual | Valores por colonia (`cvegeo` de 13 dígitos). |
|
|
214
|
+
| `modo` | `'kpi' \| 'conteo'` | Solo lectura (refleja el atributo). |
|
|
215
|
+
| `niveles` | `1 \| 2 \| 3 \| 4` | Refleja el atributo `niveles`. |
|
|
216
|
+
| `colorear` | `boolean` | `false` pinta todo en gris. |
|
|
217
|
+
| `listo` | `Promise<void>` | Se resuelve cuando el mapa está dibujado. |
|
|
218
|
+
|
|
219
|
+
### Métodos
|
|
220
|
+
|
|
221
|
+
| Método | Devuelve |
|
|
222
|
+
|---|---|
|
|
223
|
+
| `setKpi(datos, opciones?)` | `{ cargados, ignoradas }`, o `null` si aún carga (se aplica al terminar). `opciones`: texto de origen o `{ nivel: 'municipio' \| 'cp' \| 'colonia', origen }`. |
|
|
224
|
+
| `getKpi(nivel?)` | Valores de un nivel (municipio por omisión). |
|
|
225
|
+
| `kpiEntidades()` | Valor por entidad (`cve_ent` → valor o `null`). |
|
|
226
|
+
| `kpiNacional()` | Valor nacional (ponderado o suma, según el modo). |
|
|
227
|
+
| `abrirEntidad(cve_ent)` | Muestra los municipios de una entidad. |
|
|
228
|
+
| `abrirMunicipio(cve_geo)` | `Promise`. Abre el municipio con sus CP y colonias (sin la entidad importada o con `niveles` < 3, abre la entidad y lo selecciona). |
|
|
229
|
+
| `abrirCp(cp, cve_geo?)` | `Promise`. Abre un CP y muestra sus colonias (con `niveles="3"`, solo lo selecciona). |
|
|
230
|
+
| `seleccionar(cve_geo)` | Abre la entidad y selecciona el municipio. |
|
|
231
|
+
| `seleccionarColonia(cvegeo)` | `Promise`. Abre municipio y CP de la colonia y la selecciona. |
|
|
232
|
+
| `subir()` | Sube un nivel, sin pasar de `raiz`. También con la tecla Escape. |
|
|
233
|
+
| `nacional()` | Vuelve a la vista nacional (o a la raíz). |
|
|
234
|
+
| `localizar(lat, lon, mover = true)` | `{ cve_ent, cve_geo, entidad, municipio, kpi }` y, si la geometría del municipio ya está cargada, `cp`, `kpi_cp`, `cve_col`, `colonia`, `kpi_colonia`. Con `mover`, navega y marca el punto. |
|
|
235
|
+
| `localizarDetalle(lat, lon, mover = true)` | `Promise` con lo mismo, cargando antes la geometría de CP/colonias. |
|
|
236
|
+
| `aleatorio(semilla?, huecos?)` | Genera datos de prueba (también para CP y colonias de las entidades importadas). |
|
|
237
|
+
| `encuadrarVista()` | Reencuadra la vista actual. |
|
|
238
|
+
| `redibujar()` | Vuelve a leer los colores CSS y redibuja. |
|
|
239
|
+
|
|
240
|
+
### Formatos aceptados por `kpi` / `setKpi`
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
{ "22014": 78.5, "22011": 41 } // objeto clave → valor
|
|
244
|
+
[{ cve_geo: "22014", kpi: 78.5 }, { cve: 22011, valor: 41 }] // filas (cve_geo|cve|clave|cp|cvegeo, kpi|valor|value)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Las claves se rellenan con ceros a la izquierda (`1001` → `01001`). Para leer un CSV ya tienes `leerCsv(texto)` exportado por el paquete.
|
|
248
|
+
|
|
249
|
+
### Eventos
|
|
250
|
+
|
|
251
|
+
Todos son `CustomEvent`, burbujean y salen del Shadow DOM.
|
|
252
|
+
|
|
253
|
+
| Evento | `detail` |
|
|
254
|
+
|---|---|
|
|
255
|
+
| `mapa-listo` | — |
|
|
256
|
+
| `mapa-error` | `{ error }` (no se pudo cargar la geometría) |
|
|
257
|
+
| `kpi-cambio` | `{ cargados, ignoradas, origen, nivel }` |
|
|
258
|
+
| `seleccion` | `{ tipo: 'municipio' \| 'cp' \| 'colonia', clave, nombre, cve_geo, cve_ent, municipio, entidad, kpi, poblacion }` (+ `cp`, `cve_col`, `colonia`, `tipo_asentamiento` según el tipo), o `null` al deseleccionar |
|
|
259
|
+
| `nivel-cambio` | `{ nivel: 'nacional' \| 'entidad' \| 'municipio' \| 'cp', cve_ent, entidad, cve_geo, municipio, cp }` |
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Estilos
|
|
264
|
+
|
|
265
|
+
El componente toma la **tipografía de tu página**. Necesita una altura: por omisión mide 640 px.
|
|
266
|
+
|
|
267
|
+
```css
|
|
268
|
+
multinom-mapa {
|
|
269
|
+
height: calc(100vh - 64px);
|
|
270
|
+
--mk-accent: #c2185b; /* color de selección y enlaces */
|
|
271
|
+
--mk-bg: transparent; /* fondo detrás de las tarjetas */
|
|
272
|
+
--mk-relleno: 0; /* margen interno */
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Variables disponibles: `--mk-bg`, `--mk-panel`, `--mk-ink`, `--mk-ink2`, `--mk-muted`, `--mk-line`, `--mk-land`, `--mk-edge`, `--mk-accent`, `--mk-nodata`, `--mk-hatch`, `--mk-halo`, `--mk-mono`, `--mk-relleno`. Si las cambias en caliente, llama a `redibujar()` para que el canvas las tome.
|
|
277
|
+
|
|
278
|
+
Partes para `::part()`: `app`, `encabezado`, `mapa`, `leyenda`, `panel`.
|
|
279
|
+
|
|
280
|
+
Por debajo de 760 px **de ancho del componente** (no de la ventana), el panel pasa debajo del mapa.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## La geometría
|
|
285
|
+
|
|
286
|
+
Por omisión el componente hace `import('./datos.js')` del propio paquete; tu bundler (Angular CLI con webpack o esbuild, Vite, etc.) lo separa en su propio chunk y solo se descarga cuando aparece el primer mapa. No hay que configurar nada.
|
|
287
|
+
|
|
288
|
+
Si prefieres servirla como archivo estático (por ejemplo, desde un CDN), copia el JSON a tus assets en `angular.json`:
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
"assets": [
|
|
292
|
+
{ "glob": "mexico.json", "input": "node_modules/multinom_mapa/dist", "output": "assets/multinom-mapa" }
|
|
293
|
+
]
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
y apúntalo con el atributo o de forma global:
|
|
297
|
+
|
|
298
|
+
```html
|
|
299
|
+
<multinom-mapa datos-url="assets/multinom-mapa/mexico.json"></multinom-mapa>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
import { configurarDatosUrl } from 'multinom_mapa';
|
|
304
|
+
configurarDatosUrl('assets/multinom-mapa/mexico.json');
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Otros entornos
|
|
310
|
+
|
|
311
|
+
**HTML plano**
|
|
312
|
+
|
|
313
|
+
```html
|
|
314
|
+
<script type="module">import 'https://cdn.jsdelivr.net/npm/multinom_mapa@1/dist/index.js';</script>
|
|
315
|
+
<multinom-mapa demo></multinom-mapa>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**React 19+** pasa propiedades y eventos a custom elements de forma nativa:
|
|
319
|
+
`<multinom-mapa kpi={valores} onseleccion={e => …} />`.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Desarrollo y publicación
|
|
324
|
+
|
|
325
|
+
El código fuente vive en el repo de GitHub; npmjs.com solo recibe el paquete compilado.
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
npm install # instala dependencias y compila (script prepare)
|
|
329
|
+
npm run build # recompila dist/
|
|
330
|
+
npm pack # opcional: genera el .tgz para revisarlo antes de publicar
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Primera publicación (una sola vez, desde tu computadora)
|
|
334
|
+
|
|
335
|
+
Trusted Publishing solo se puede configurar en un paquete que ya existe, así que la primera versión se publica a mano:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
npm login # cuenta de npmjs.com con 2FA
|
|
339
|
+
npm publish # compila (script prepare) y sube multinom_mapa@<versión de package.json>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Luego, en npmjs.com → paquete `multinom_mapa` → *Settings* → *Trusted Publisher* → **GitHub Actions**:
|
|
343
|
+
|
|
344
|
+
| Campo | Valor |
|
|
345
|
+
|---|---|
|
|
346
|
+
| Organization or user | `MULTIEVAL` |
|
|
347
|
+
| Repository | `multinom_mapa` |
|
|
348
|
+
| Workflow filename | `publicar.yml` |
|
|
349
|
+
| Environment | (vacío) |
|
|
350
|
+
|
|
351
|
+
Con eso GitHub Actions publica sin token guardado (npm verifica la identidad del flujo con OIDC). Opcional y recomendado: en el mismo *Settings* → *Publishing access*, exige 2FA y deshabilita los tokens, para que solo se pueda publicar desde el flujo o con tu 2FA.
|
|
352
|
+
|
|
353
|
+
### Publicar una versión nueva
|
|
354
|
+
|
|
355
|
+
La publicación es automática con GitHub Actions (`.github/workflows/publicar.yml`): se dispara al subir una etiqueta `v*`.
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
npm version minor # 1.1.0 → 1.2.0: cambia package.json, hace commit y crea la etiqueta v1.2.0
|
|
359
|
+
git push --follow-tags # sube el commit y la etiqueta; Actions publica en npm
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Usa `patch` para correcciones (1.1.1), `minor` para funciones nuevas compatibles (1.2.0) y `major` si rompes algo de la API (2.0.0). El flujo se detiene si la etiqueta no coincide con la versión de `package.json`.
|
|
363
|
+
|
|
364
|
+
En los proyectos Angular actualizas con `npm install multinom_mapa@latest` (o la versión que quieras).
|
|
365
|
+
|
|
366
|
+
### Dueños del paquete
|
|
367
|
+
|
|
368
|
+
El paquete queda a nombre de la cuenta que lo publica primero. Para pasarlo a otra cuenta u organización, sin cambiar el nombre ni los `import` de los proyectos:
|
|
369
|
+
|
|
370
|
+
- **Otra cuenta como dueña:** `npm owner add <usuario> multinom_mapa` (todos los dueños tienen los mismos permisos; luego `npm owner rm <usuario>` para quitar la anterior).
|
|
371
|
+
- **Una organización de npm:** en npmjs.com → paquete → *Settings* → transferir a la organización; los permisos se manejan después por equipos.
|
|
372
|
+
|
|
373
|
+
### Visibilidad
|
|
374
|
+
|
|
375
|
+
`multinom_mapa` es un nombre **sin scope**, y en npm esos paquetes siempre son públicos. Si algún día necesitaras uno privado, tendría que publicarse con otro nombre que lleve scope (por ejemplo `@tu-org/multinom_mapa`) y cambiar el `import` en los proyectos.
|
|
376
|
+
|
|
377
|
+
## Licencia
|
|
378
|
+
|
|
379
|
+
El código es [MIT](./LICENSE), © MULTIEVAL. Los datos geográficos y estadísticos tienen licencias propias (geoBoundaries ODbL, INEGI términos de libre uso, SEPOMEX CC BY 4.0); en conjunto se distribuyen bajo ODbL. Ver [LICENCIA-DATOS.md](./LICENCIA-DATOS.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multinom_mapa",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Web Component <multinom-mapa>: mapa de México por entidad, municipio, código postal y colonia, coloreado por un KPI o por cantidades. Funciona en cualquier versión de Angular, en React, Vue o HTML plano.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|