@cerca.red/mapa 0.2.0
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 +133 -0
- package/dist/capas.d.ts +29 -0
- package/dist/capas.js +489 -0
- package/dist/capas.js.map +1 -0
- package/dist/doble/estiloFalso.d.ts +19 -0
- package/dist/doble/estiloFalso.js +33 -0
- package/dist/doble/estiloFalso.js.map +1 -0
- package/dist/doble/index.d.ts +11 -0
- package/dist/doble/index.js +12 -0
- package/dist/doble/index.js.map +1 -0
- package/dist/doble/mapaFalso.d.ts +75 -0
- package/dist/doble/mapaFalso.js +535 -0
- package/dist/doble/mapaFalso.js.map +1 -0
- package/dist/encuadre.d.ts +64 -0
- package/dist/encuadre.js +83 -0
- package/dist/encuadre.js.map +1 -0
- package/dist/estilo.d.ts +88 -0
- package/dist/estilo.js +23 -0
- package/dist/estilo.js.map +1 -0
- package/dist/eventos.d.ts +127 -0
- package/dist/eventos.js +69 -0
- package/dist/eventos.js.map +1 -0
- package/dist/identificadores.d.ts +109 -0
- package/dist/identificadores.js +104 -0
- package/dist/identificadores.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/manifiesto.d.ts +97 -0
- package/dist/manifiesto.js +156 -0
- package/dist/manifiesto.js.map +1 -0
- package/dist/modelo.d.ts +154 -0
- package/dist/modelo.js +227 -0
- package/dist/modelo.js.map +1 -0
- package/dist/navegador/index.d.ts +70 -0
- package/dist/navegador/index.js +132 -0
- package/dist/navegador/index.js.map +1 -0
- package/dist/navegador/maplibre.d.ts +41 -0
- package/dist/navegador/maplibre.js +463 -0
- package/dist/navegador/maplibre.js.map +1 -0
- package/dist/navegador/protocolo.d.ts +4 -0
- package/dist/navegador/protocolo.js +55 -0
- package/dist/navegador/protocolo.js.map +1 -0
- package/dist/navegador/webgl.d.ts +24 -0
- package/dist/navegador/webgl.js +47 -0
- package/dist/navegador/webgl.js.map +1 -0
- package/dist/navegador/worker.d.ts +33 -0
- package/dist/navegador/worker.js +47 -0
- package/dist/navegador/worker.js.map +1 -0
- package/dist/paleta.d.ts +53 -0
- package/dist/paleta.js +53 -0
- package/dist/paleta.js.map +1 -0
- package/dist/proyecciones.d.ts +160 -0
- package/dist/proyecciones.js +2 -0
- package/dist/proyecciones.js.map +1 -0
- package/dist/puerto.d.ts +244 -0
- package/dist/puerto.js +2 -0
- package/dist/puerto.js.map +1 -0
- package/dist/sdk.d.ts +111 -0
- package/dist/sdk.js +552 -0
- package/dist/sdk.js.map +1 -0
- package/dist/sincronizacion.d.ts +40 -0
- package/dist/sincronizacion.js +144 -0
- package/dist/sincronizacion.js.map +1 -0
- package/dist/worker-de-maplibre.d.ts +36 -0
- package/dist/worker-de-maplibre.js +37 -0
- package/dist/worker-de-maplibre.js.map +1 -0
- package/package.json +59 -0
package/dist/puerto.d.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import type { Caja, ColeccionDeEntidades, Coordenada } from "@cerca.red/geo";
|
|
2
|
+
import type { CapaDelEstilo, EspecificacionDeEstilo } from "./estilo.ts";
|
|
3
|
+
/**
|
|
4
|
+
* El puerto: todo lo que este SDK le pide a un motor de mapas.
|
|
5
|
+
*
|
|
6
|
+
* ## Por qué existe
|
|
7
|
+
*
|
|
8
|
+
* Tres razones, y las tres se pagan solas.
|
|
9
|
+
*
|
|
10
|
+
* **Una.** El núcleo del SDK no importa `maplibre-gl`, así que el punto de
|
|
11
|
+
* entrada por defecto de este paquete se puede importar desde un Server
|
|
12
|
+
* Component de Next sobre Workers sin que el build reviente. Quien quiera el
|
|
13
|
+
* mapa de verdad entra por `@cerca.red/mapa/navegador`, y eso **se ve en el
|
|
14
|
+
* diff**.
|
|
15
|
+
*
|
|
16
|
+
* **Dos.** Esta interfaz es la lista escrita de lo que hay que revisar el día
|
|
17
|
+
* que salga MapLibre 7. La 6 ya rompió tres cosas —`map.transform` dejó de
|
|
18
|
+
* existir, `setData()` perdió la espera y el retorno encadenable, y el evento
|
|
19
|
+
* de datos se partió en dos tipos—, y cada una se arregla en un archivo
|
|
20
|
+
* (`navegador/maplibre.ts`) en vez de en cuarenta.
|
|
21
|
+
*
|
|
22
|
+
* **Tres.** Con el puerto, casi todo el SDK se prueba en Node contra un doble
|
|
23
|
+
* y sin GPU. Lo que no se puede probar así queda acotado a lo que de verdad
|
|
24
|
+
* necesita WebGL, que es poco y va a Playwright.
|
|
25
|
+
*
|
|
26
|
+
* ## La regla de crecimiento
|
|
27
|
+
*
|
|
28
|
+
* Se le suman métodos **cuando hacen falta**, no por si acaso. Cada método de
|
|
29
|
+
* más es una cosa más que el doble tiene que fingir bien y una cosa más que
|
|
30
|
+
* revisar en la próxima versión mayor de MapLibre.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Quién movió la cámara.
|
|
34
|
+
*
|
|
35
|
+
* Es el campo que rompe el bucle lista↔mapa. Sin él, la pantalla que escucha
|
|
36
|
+
* el movimiento para recargar resultados no puede distinguir «el usuario
|
|
37
|
+
* arrastró el mapa» de «yo acabo de encuadrar el resultado que el usuario
|
|
38
|
+
* eligió en la lista», así que vuelve a consultar por su propio movimiento,
|
|
39
|
+
* lo que mueve el mapa, lo que dispara otro evento.
|
|
40
|
+
*/
|
|
41
|
+
export type OrigenDeMovimiento = "usuario" | "codigo";
|
|
42
|
+
/** Un punto en píxeles del canvas, con el origen en la esquina superior izquierda. */
|
|
43
|
+
export interface PuntoEnPantalla {
|
|
44
|
+
readonly x: number;
|
|
45
|
+
readonly y: number;
|
|
46
|
+
}
|
|
47
|
+
/** Dónde está mirando la cámara. */
|
|
48
|
+
export interface VistaDelMapa {
|
|
49
|
+
readonly centro: Coordenada;
|
|
50
|
+
readonly zoom: number;
|
|
51
|
+
/** Grados desde el norte, en el sentido de las agujas del reloj. */
|
|
52
|
+
readonly rumbo: number;
|
|
53
|
+
/** Grados de inclinación respecto a la vertical: 0 es cenital. */
|
|
54
|
+
readonly inclinacion: number;
|
|
55
|
+
/** La caja que se ve ahora mismo. */
|
|
56
|
+
readonly caja: Caja;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Espacio en píxeles que la cámara deja libre en cada borde.
|
|
60
|
+
*
|
|
61
|
+
* En móvil no es un detalle estético: una hoja inferior que ocupa media
|
|
62
|
+
* pantalla hace que el centro del canvas **no** sea el centro de lo que el
|
|
63
|
+
* usuario ve, y sin márgenes cada encuadre deja los resultados debajo de la
|
|
64
|
+
* hoja.
|
|
65
|
+
*/
|
|
66
|
+
export interface Margenes {
|
|
67
|
+
readonly arriba: number;
|
|
68
|
+
readonly derecha: number;
|
|
69
|
+
readonly abajo: number;
|
|
70
|
+
readonly izquierda: number;
|
|
71
|
+
}
|
|
72
|
+
/** Adónde llevar la cámara. Todo opcional: lo que no se diga, no se toca. */
|
|
73
|
+
export interface DestinoDeCamara {
|
|
74
|
+
readonly centro?: Coordenada;
|
|
75
|
+
readonly zoom?: number;
|
|
76
|
+
readonly rumbo?: number;
|
|
77
|
+
readonly inclinacion?: number;
|
|
78
|
+
}
|
|
79
|
+
/** Cómo llegar. */
|
|
80
|
+
export interface OpcionesDeMovimiento {
|
|
81
|
+
readonly origen: OrigenDeMovimiento;
|
|
82
|
+
/**
|
|
83
|
+
* `"vuelo"` es la curva larga de MapLibre, que hace zoom hacia fuera y
|
|
84
|
+
* luego hacia dentro; `"suave"` interpola en línea recta; `"salto"` no
|
|
85
|
+
* anima.
|
|
86
|
+
*
|
|
87
|
+
* Importa cuál se elige: el vuelo a un punto muy cercano se ve como un
|
|
88
|
+
* tirón hacia atrás y hacia delante, y es la razón por la que encuadrar un
|
|
89
|
+
* solo negocio usa `"suave"`.
|
|
90
|
+
*/
|
|
91
|
+
readonly modo?: "vuelo" | "suave" | "salto";
|
|
92
|
+
readonly duracionEnMs?: number;
|
|
93
|
+
}
|
|
94
|
+
export interface OpcionesDeEncuadre extends OpcionesDeMovimiento {
|
|
95
|
+
readonly margenes?: Margenes;
|
|
96
|
+
/** El zoom más allá del cual no se acerca aunque la caja quepa. */
|
|
97
|
+
readonly zoomMaximo?: number;
|
|
98
|
+
}
|
|
99
|
+
/** Una entidad que el motor tiene dibujada bajo un punto de la pantalla. */
|
|
100
|
+
export interface EntidadDibujada {
|
|
101
|
+
readonly capa: string;
|
|
102
|
+
readonly id: string | number | undefined;
|
|
103
|
+
readonly propiedades: Readonly<Record<string, unknown>>;
|
|
104
|
+
}
|
|
105
|
+
/** Opciones de una fuente GeoJSON. Solo las que este SDK usa. */
|
|
106
|
+
export interface OpcionesDeFuente {
|
|
107
|
+
/** Agrupa los puntos cercanos. La agrupación la hace el motor, no el SDK. */
|
|
108
|
+
readonly agrupar?: boolean;
|
|
109
|
+
readonly radioDeGrupoEnPx?: number;
|
|
110
|
+
/** Zoom a partir del cual se dejan de agrupar. */
|
|
111
|
+
readonly zoomMaximoDeGrupo?: number;
|
|
112
|
+
/** Necesario para poder darle estado a una entidad por su identificador. */
|
|
113
|
+
readonly promoverId?: string;
|
|
114
|
+
}
|
|
115
|
+
/** Una imagen registrada para usarse como símbolo. */
|
|
116
|
+
export interface ImagenDeSimbolo {
|
|
117
|
+
readonly ancho: number;
|
|
118
|
+
readonly alto: number;
|
|
119
|
+
readonly datos: Uint8ClampedArray | Uint8Array;
|
|
120
|
+
/**
|
|
121
|
+
* `true` si es una imagen de campo de distancia con signo, que es lo que
|
|
122
|
+
* permite recolorearla desde el estilo en vez de generar una imagen por
|
|
123
|
+
* cada combinación de estado y color.
|
|
124
|
+
*/
|
|
125
|
+
readonly sdf?: boolean;
|
|
126
|
+
readonly escalaDePixeles?: number;
|
|
127
|
+
}
|
|
128
|
+
/** Lo que devuelve suscribirse: llamarlo cancela la suscripción. */
|
|
129
|
+
export type Desuscribir = () => void;
|
|
130
|
+
/** El evento de un cambio de cámara. */
|
|
131
|
+
export interface EventoDeCamara {
|
|
132
|
+
readonly origen: OrigenDeMovimiento;
|
|
133
|
+
readonly vista: VistaDelMapa;
|
|
134
|
+
}
|
|
135
|
+
/** El evento de un toque o un clic sobre el mapa. */
|
|
136
|
+
export interface EventoDePuntero {
|
|
137
|
+
readonly coordenada: Coordenada;
|
|
138
|
+
readonly punto: PuntoEnPantalla;
|
|
139
|
+
/**
|
|
140
|
+
* `true` si vino de un dedo o de un ratón, `false` si vino del teclado.
|
|
141
|
+
*
|
|
142
|
+
* Un canvas no es accesible por sí solo: el recorrido con teclado necesita
|
|
143
|
+
* una lista real al lado, y quien la escucha tiene que poder decidir
|
|
144
|
+
* distinto —no abrir una tarjeta flotante bajo un dedo que no existe—.
|
|
145
|
+
*/
|
|
146
|
+
readonly desdePuntero: boolean;
|
|
147
|
+
}
|
|
148
|
+
/** Lo que un motor de mapas avisa. */
|
|
149
|
+
export interface EventosNativos {
|
|
150
|
+
/** El estilo terminó de cargar. Se vuelve a emitir en cada cambio de estilo. */
|
|
151
|
+
readonly "estilo:listo": undefined;
|
|
152
|
+
/** Una fuente terminó de recibir datos. Lleva el identificador de la fuente. */
|
|
153
|
+
readonly "fuente:datos": {
|
|
154
|
+
readonly fuente: string;
|
|
155
|
+
};
|
|
156
|
+
readonly movimiento: EventoDeCamara;
|
|
157
|
+
readonly "movimiento:fin": EventoDeCamara;
|
|
158
|
+
readonly zoom: EventoDeCamara;
|
|
159
|
+
readonly clic: EventoDePuntero;
|
|
160
|
+
readonly error: {
|
|
161
|
+
readonly error: Error;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/** Lo que un motor de mapas avisa sobre capas concretas. */
|
|
165
|
+
export interface EventosDeCapa {
|
|
166
|
+
readonly clic: EventoDePuntero & {
|
|
167
|
+
readonly entidades: readonly EntidadDibujada[];
|
|
168
|
+
};
|
|
169
|
+
readonly encima: EventoDePuntero & {
|
|
170
|
+
readonly entidades: readonly EntidadDibujada[];
|
|
171
|
+
};
|
|
172
|
+
readonly fuera: EventoDePuntero;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* El motor de mapas, visto desde el SDK.
|
|
176
|
+
*
|
|
177
|
+
* Lo implementan dos cosas: `navegador/maplibre.ts`, que envuelve MapLibre de
|
|
178
|
+
* verdad, y `doble/`, que finge lo justo para que las pruebas en Node midan
|
|
179
|
+
* el comportamiento del SDK y no el del motor.
|
|
180
|
+
*/
|
|
181
|
+
export interface MapaNativo {
|
|
182
|
+
/** `true` cuando el estilo ya cargó y se le pueden añadir capas. */
|
|
183
|
+
estaListo(): boolean;
|
|
184
|
+
/** Se resuelve cuando `estaListo()` pasa a ser cierto. Si ya lo era, de inmediato. */
|
|
185
|
+
cuandoListo(): Promise<void>;
|
|
186
|
+
/** Suelta el contexto WebGL y todos los oyentes. Después de esto no se le habla más. */
|
|
187
|
+
destruir(): void;
|
|
188
|
+
/** Vuelve a medir el contenedor. Hace falta cuando la hoja inferior cambia de alto. */
|
|
189
|
+
redimensionar(): void;
|
|
190
|
+
/**
|
|
191
|
+
* Reemplaza el estilo entero.
|
|
192
|
+
*
|
|
193
|
+
* Cambiar de tema o de idioma es esto, y por eso el SDK guarda su propio
|
|
194
|
+
* modelo: el estilo nuevo llega sin las fuentes ni las capas de Cerca, y
|
|
195
|
+
* hay que volver a ponerlas. No es un defecto que evitar — es lo que
|
|
196
|
+
* garantiza que el orden de capas quede bien por construcción.
|
|
197
|
+
*/
|
|
198
|
+
ponerEstilo(estilo: EspecificacionDeEstilo): void;
|
|
199
|
+
agregarFuenteGeoJSON(id: string, datos: ColeccionDeEntidades, opciones?: OpcionesDeFuente): void;
|
|
200
|
+
/**
|
|
201
|
+
* Cambia los datos de una fuente ya añadida.
|
|
202
|
+
*
|
|
203
|
+
* En MapLibre 6 esto **no dice cuándo aterrizó el dato**: `setData()` perdió
|
|
204
|
+
* la opción de esperar y ya no devuelve el mapa. Quien necesite encuadrar
|
|
205
|
+
* después de poner datos escucha `fuente:datos`.
|
|
206
|
+
*/
|
|
207
|
+
ponerDatosDeFuente(id: string, datos: ColeccionDeEntidades): void;
|
|
208
|
+
tieneFuente(id: string): boolean;
|
|
209
|
+
/** Añade una capa, opcionalmente por debajo de otra que ya exista. */
|
|
210
|
+
agregarCapa(capa: CapaDelEstilo, antesDe?: string): void;
|
|
211
|
+
quitarCapa(id: string): void;
|
|
212
|
+
tieneCapa(id: string): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Marca una entidad de una fuente con un estado que el estilo puede leer.
|
|
215
|
+
*
|
|
216
|
+
* Sirve para lo que **solo cambia color** —el resalte al pasar por encima—.
|
|
217
|
+
* Para lo que tiene que dibujarse **encima** de sus vecinos hace falta otra
|
|
218
|
+
* fuente, porque la clave de ordenación de símbolos no lee el estado de
|
|
219
|
+
* entidad. Es la razón por la que la selección vive en su propia fuente.
|
|
220
|
+
*/
|
|
221
|
+
ponerEstadoDeEntidad(fuente: string, id: string | number, estado: Readonly<Record<string, unknown>>): void;
|
|
222
|
+
limpiarEstadosDeEntidad(fuente: string): void;
|
|
223
|
+
agregarImagen(id: string, imagen: ImagenDeSimbolo): void;
|
|
224
|
+
tieneImagen(id: string): boolean;
|
|
225
|
+
vista(): VistaDelMapa;
|
|
226
|
+
moverCamara(destino: DestinoDeCamara, opciones: OpcionesDeMovimiento): void;
|
|
227
|
+
encuadrarCaja(caja: Caja, opciones: OpcionesDeEncuadre): void;
|
|
228
|
+
ponerMargenes(margenes: Margenes): void;
|
|
229
|
+
/** Limita hasta dónde se puede navegar. `undefined` quita el límite. */
|
|
230
|
+
ponerCajaMaxima(caja: Caja | undefined): void;
|
|
231
|
+
/**
|
|
232
|
+
* De coordenada a píxel.
|
|
233
|
+
*
|
|
234
|
+
* Es lo que hace comprobable el objetivo táctil de 44 px sobre un canvas,
|
|
235
|
+
* donde no hay ningún elemento del DOM cuya caja medir: se calcula el punto
|
|
236
|
+
* y se toca dentro y fuera del radio esperado.
|
|
237
|
+
*/
|
|
238
|
+
proyectar(coordenada: Coordenada): PuntoEnPantalla;
|
|
239
|
+
desproyectar(punto: PuntoEnPantalla): Coordenada;
|
|
240
|
+
/** Las entidades dibujadas bajo un punto, en las capas dadas. */
|
|
241
|
+
entidadesEn(punto: PuntoEnPantalla, capas: readonly string[]): readonly EntidadDibujada[];
|
|
242
|
+
al<T extends keyof EventosNativos>(tipo: T, manejador: (evento: EventosNativos[T]) => void): Desuscribir;
|
|
243
|
+
alDeCapa<T extends keyof EventosDeCapa>(tipo: T, capas: readonly string[], manejador: (evento: EventosDeCapa[T]) => void): Desuscribir;
|
|
244
|
+
}
|
package/dist/puerto.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"puerto.js","sourceRoot":"","sources":["../src/puerto.ts"],"names":[],"mappings":"","sourcesContent":["import type { Caja, ColeccionDeEntidades, Coordenada } from \"@cerca.red/geo\";\n\nimport type { CapaDelEstilo, EspecificacionDeEstilo } from \"./estilo.ts\";\n\n/**\n * El puerto: todo lo que este SDK le pide a un motor de mapas.\n *\n * ## Por qué existe\n *\n * Tres razones, y las tres se pagan solas.\n *\n * **Una.** El núcleo del SDK no importa `maplibre-gl`, así que el punto de\n * entrada por defecto de este paquete se puede importar desde un Server\n * Component de Next sobre Workers sin que el build reviente. Quien quiera el\n * mapa de verdad entra por `@cerca.red/mapa/navegador`, y eso **se ve en el\n * diff**.\n *\n * **Dos.** Esta interfaz es la lista escrita de lo que hay que revisar el día\n * que salga MapLibre 7. La 6 ya rompió tres cosas —`map.transform` dejó de\n * existir, `setData()` perdió la espera y el retorno encadenable, y el evento\n * de datos se partió en dos tipos—, y cada una se arregla en un archivo\n * (`navegador/maplibre.ts`) en vez de en cuarenta.\n *\n * **Tres.** Con el puerto, casi todo el SDK se prueba en Node contra un doble\n * y sin GPU. Lo que no se puede probar así queda acotado a lo que de verdad\n * necesita WebGL, que es poco y va a Playwright.\n *\n * ## La regla de crecimiento\n *\n * Se le suman métodos **cuando hacen falta**, no por si acaso. Cada método de\n * más es una cosa más que el doble tiene que fingir bien y una cosa más que\n * revisar en la próxima versión mayor de MapLibre.\n */\n\n/**\n * Quién movió la cámara.\n *\n * Es el campo que rompe el bucle lista↔mapa. Sin él, la pantalla que escucha\n * el movimiento para recargar resultados no puede distinguir «el usuario\n * arrastró el mapa» de «yo acabo de encuadrar el resultado que el usuario\n * eligió en la lista», así que vuelve a consultar por su propio movimiento,\n * lo que mueve el mapa, lo que dispara otro evento.\n */\nexport type OrigenDeMovimiento = \"usuario\" | \"codigo\";\n\n/** Un punto en píxeles del canvas, con el origen en la esquina superior izquierda. */\nexport interface PuntoEnPantalla {\n readonly x: number;\n readonly y: number;\n}\n\n/** Dónde está mirando la cámara. */\nexport interface VistaDelMapa {\n readonly centro: Coordenada;\n readonly zoom: number;\n /** Grados desde el norte, en el sentido de las agujas del reloj. */\n readonly rumbo: number;\n /** Grados de inclinación respecto a la vertical: 0 es cenital. */\n readonly inclinacion: number;\n /** La caja que se ve ahora mismo. */\n readonly caja: Caja;\n}\n\n/**\n * Espacio en píxeles que la cámara deja libre en cada borde.\n *\n * En móvil no es un detalle estético: una hoja inferior que ocupa media\n * pantalla hace que el centro del canvas **no** sea el centro de lo que el\n * usuario ve, y sin márgenes cada encuadre deja los resultados debajo de la\n * hoja.\n */\nexport interface Margenes {\n readonly arriba: number;\n readonly derecha: number;\n readonly abajo: number;\n readonly izquierda: number;\n}\n\n/** Adónde llevar la cámara. Todo opcional: lo que no se diga, no se toca. */\nexport interface DestinoDeCamara {\n readonly centro?: Coordenada;\n readonly zoom?: number;\n readonly rumbo?: number;\n readonly inclinacion?: number;\n}\n\n/** Cómo llegar. */\nexport interface OpcionesDeMovimiento {\n readonly origen: OrigenDeMovimiento;\n /**\n * `\"vuelo\"` es la curva larga de MapLibre, que hace zoom hacia fuera y\n * luego hacia dentro; `\"suave\"` interpola en línea recta; `\"salto\"` no\n * anima.\n *\n * Importa cuál se elige: el vuelo a un punto muy cercano se ve como un\n * tirón hacia atrás y hacia delante, y es la razón por la que encuadrar un\n * solo negocio usa `\"suave\"`.\n */\n readonly modo?: \"vuelo\" | \"suave\" | \"salto\";\n readonly duracionEnMs?: number;\n}\n\nexport interface OpcionesDeEncuadre extends OpcionesDeMovimiento {\n readonly margenes?: Margenes;\n /** El zoom más allá del cual no se acerca aunque la caja quepa. */\n readonly zoomMaximo?: number;\n}\n\n/** Una entidad que el motor tiene dibujada bajo un punto de la pantalla. */\nexport interface EntidadDibujada {\n readonly capa: string;\n readonly id: string | number | undefined;\n readonly propiedades: Readonly<Record<string, unknown>>;\n}\n\n/** Opciones de una fuente GeoJSON. Solo las que este SDK usa. */\nexport interface OpcionesDeFuente {\n /** Agrupa los puntos cercanos. La agrupación la hace el motor, no el SDK. */\n readonly agrupar?: boolean;\n readonly radioDeGrupoEnPx?: number;\n /** Zoom a partir del cual se dejan de agrupar. */\n readonly zoomMaximoDeGrupo?: number;\n /** Necesario para poder darle estado a una entidad por su identificador. */\n readonly promoverId?: string;\n}\n\n/** Una imagen registrada para usarse como símbolo. */\nexport interface ImagenDeSimbolo {\n readonly ancho: number;\n readonly alto: number;\n readonly datos: Uint8ClampedArray | Uint8Array;\n /**\n * `true` si es una imagen de campo de distancia con signo, que es lo que\n * permite recolorearla desde el estilo en vez de generar una imagen por\n * cada combinación de estado y color.\n */\n readonly sdf?: boolean;\n readonly escalaDePixeles?: number;\n}\n\n/** Lo que devuelve suscribirse: llamarlo cancela la suscripción. */\nexport type Desuscribir = () => void;\n\n/** El evento de un cambio de cámara. */\nexport interface EventoDeCamara {\n readonly origen: OrigenDeMovimiento;\n readonly vista: VistaDelMapa;\n}\n\n/** El evento de un toque o un clic sobre el mapa. */\nexport interface EventoDePuntero {\n readonly coordenada: Coordenada;\n readonly punto: PuntoEnPantalla;\n /**\n * `true` si vino de un dedo o de un ratón, `false` si vino del teclado.\n *\n * Un canvas no es accesible por sí solo: el recorrido con teclado necesita\n * una lista real al lado, y quien la escucha tiene que poder decidir\n * distinto —no abrir una tarjeta flotante bajo un dedo que no existe—.\n */\n readonly desdePuntero: boolean;\n}\n\n/** Lo que un motor de mapas avisa. */\nexport interface EventosNativos {\n /** El estilo terminó de cargar. Se vuelve a emitir en cada cambio de estilo. */\n readonly \"estilo:listo\": undefined;\n /** Una fuente terminó de recibir datos. Lleva el identificador de la fuente. */\n readonly \"fuente:datos\": { readonly fuente: string };\n readonly movimiento: EventoDeCamara;\n readonly \"movimiento:fin\": EventoDeCamara;\n readonly zoom: EventoDeCamara;\n readonly clic: EventoDePuntero;\n readonly error: { readonly error: Error };\n}\n\n/** Lo que un motor de mapas avisa sobre capas concretas. */\nexport interface EventosDeCapa {\n readonly clic: EventoDePuntero & {\n readonly entidades: readonly EntidadDibujada[];\n };\n readonly encima: EventoDePuntero & {\n readonly entidades: readonly EntidadDibujada[];\n };\n readonly fuera: EventoDePuntero;\n}\n\n/**\n * El motor de mapas, visto desde el SDK.\n *\n * Lo implementan dos cosas: `navegador/maplibre.ts`, que envuelve MapLibre de\n * verdad, y `doble/`, que finge lo justo para que las pruebas en Node midan\n * el comportamiento del SDK y no el del motor.\n */\nexport interface MapaNativo {\n // — ciclo de vida —\n\n /** `true` cuando el estilo ya cargó y se le pueden añadir capas. */\n estaListo(): boolean;\n /** Se resuelve cuando `estaListo()` pasa a ser cierto. Si ya lo era, de inmediato. */\n cuandoListo(): Promise<void>;\n /** Suelta el contexto WebGL y todos los oyentes. Después de esto no se le habla más. */\n destruir(): void;\n /** Vuelve a medir el contenedor. Hace falta cuando la hoja inferior cambia de alto. */\n redimensionar(): void;\n\n // — estilo —\n\n /**\n * Reemplaza el estilo entero.\n *\n * Cambiar de tema o de idioma es esto, y por eso el SDK guarda su propio\n * modelo: el estilo nuevo llega sin las fuentes ni las capas de Cerca, y\n * hay que volver a ponerlas. No es un defecto que evitar — es lo que\n * garantiza que el orden de capas quede bien por construcción.\n */\n ponerEstilo(estilo: EspecificacionDeEstilo): void;\n\n // — fuentes —\n\n agregarFuenteGeoJSON(\n id: string,\n datos: ColeccionDeEntidades,\n opciones?: OpcionesDeFuente,\n ): void;\n /**\n * Cambia los datos de una fuente ya añadida.\n *\n * En MapLibre 6 esto **no dice cuándo aterrizó el dato**: `setData()` perdió\n * la opción de esperar y ya no devuelve el mapa. Quien necesite encuadrar\n * después de poner datos escucha `fuente:datos`.\n */\n ponerDatosDeFuente(id: string, datos: ColeccionDeEntidades): void;\n tieneFuente(id: string): boolean;\n\n // — capas —\n\n /** Añade una capa, opcionalmente por debajo de otra que ya exista. */\n agregarCapa(capa: CapaDelEstilo, antesDe?: string): void;\n quitarCapa(id: string): void;\n tieneCapa(id: string): boolean;\n\n // — estado de entidad —\n\n /**\n * Marca una entidad de una fuente con un estado que el estilo puede leer.\n *\n * Sirve para lo que **solo cambia color** —el resalte al pasar por encima—.\n * Para lo que tiene que dibujarse **encima** de sus vecinos hace falta otra\n * fuente, porque la clave de ordenación de símbolos no lee el estado de\n * entidad. Es la razón por la que la selección vive en su propia fuente.\n */\n ponerEstadoDeEntidad(\n fuente: string,\n id: string | number,\n estado: Readonly<Record<string, unknown>>,\n ): void;\n limpiarEstadosDeEntidad(fuente: string): void;\n\n // — símbolos —\n\n agregarImagen(id: string, imagen: ImagenDeSimbolo): void;\n tieneImagen(id: string): boolean;\n\n // — cámara —\n\n vista(): VistaDelMapa;\n moverCamara(destino: DestinoDeCamara, opciones: OpcionesDeMovimiento): void;\n encuadrarCaja(caja: Caja, opciones: OpcionesDeEncuadre): void;\n ponerMargenes(margenes: Margenes): void;\n /** Limita hasta dónde se puede navegar. `undefined` quita el límite. */\n ponerCajaMaxima(caja: Caja | undefined): void;\n\n // — consulta —\n\n /**\n * De coordenada a píxel.\n *\n * Es lo que hace comprobable el objetivo táctil de 44 px sobre un canvas,\n * donde no hay ningún elemento del DOM cuya caja medir: se calcula el punto\n * y se toca dentro y fuera del radio esperado.\n */\n proyectar(coordenada: Coordenada): PuntoEnPantalla;\n desproyectar(punto: PuntoEnPantalla): Coordenada;\n /** Las entidades dibujadas bajo un punto, en las capas dadas. */\n entidadesEn(\n punto: PuntoEnPantalla,\n capas: readonly string[],\n ): readonly EntidadDibujada[];\n\n // — eventos —\n\n al<T extends keyof EventosNativos>(\n tipo: T,\n manejador: (evento: EventosNativos[T]) => void,\n ): Desuscribir;\n alDeCapa<T extends keyof EventosDeCapa>(\n tipo: T,\n capas: readonly string[],\n manejador: (evento: EventosDeCapa[T]) => void,\n ): Desuscribir;\n}\n"]}
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type Caja, type Coordenada, coleccionVacia } from "@cerca.red/geo";
|
|
2
|
+
import { type Anclas } from "./identificadores.ts";
|
|
3
|
+
import { type EventosDelMapa, type TipoDeEvento } from "./eventos.ts";
|
|
4
|
+
import type { FabricaDeEstilo, Tema } from "./estilo.ts";
|
|
5
|
+
import { type PaletaDelMapa } from "./paleta.ts";
|
|
6
|
+
import type { Desuscribir, DestinoDeCamara, EntidadDibujada, MapaNativo, Margenes, OpcionesDeEncuadre, OpcionesDeMovimiento, PuntoEnPantalla } from "./puerto.ts";
|
|
7
|
+
import type { BandaDeIsocrona, NegocioEnMapa, ResultadosEnMapa, RutaEnMapa, SimboloDeMapa, UbicacionDeUsuarioEnMapa, VehiculoEnMapa, ZonaEnMapa } from "./proyecciones.ts";
|
|
8
|
+
import { type CapaExtra } from "./sincronizacion.ts";
|
|
9
|
+
/**
|
|
10
|
+
* El SDK del mapa de Cerca, construido sobre el puerto.
|
|
11
|
+
*
|
|
12
|
+
* Este archivo no sabe qué es MapLibre. Recibe un `MapaNativo` ya construido
|
|
13
|
+
* —el adaptador de `navegador/`, o el doble de `doble/`— y encima pone el
|
|
14
|
+
* modelo, los eventos y las decisiones que no se deben repetir en cada
|
|
15
|
+
* superficie.
|
|
16
|
+
*/
|
|
17
|
+
export interface OpcionesDeCrearMapa {
|
|
18
|
+
/** Quien sabe construir el estilo. Función pura: mismas opciones, mismo documento. */
|
|
19
|
+
readonly estilo: FabricaDeEstilo;
|
|
20
|
+
/**
|
|
21
|
+
* La URL del archivo de teselas, **tal como vino del manifiesto**.
|
|
22
|
+
*
|
|
23
|
+
* No se compone aquí ni en ninguna superficie: ADR-024 puso las URLs
|
|
24
|
+
* absolutas en el manifiesto precisamente para que nadie las construya, y
|
|
25
|
+
* eso es lo que hace que promover un puntero a una versión anterior revierta
|
|
26
|
+
* de verdad en todas partes.
|
|
27
|
+
*/
|
|
28
|
+
readonly urlDeTeselas: string;
|
|
29
|
+
readonly tema?: Tema;
|
|
30
|
+
readonly idioma?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Los identificadores de las capas vacías donde se insertan las de Cerca.
|
|
33
|
+
*
|
|
34
|
+
* El valor por defecto son los que emite hoy `@cerca.red/mapa-estilos`, y
|
|
35
|
+
* `anclas-del-estilo.test.ts` ejecuta ese paquete para comprobar que sigue
|
|
36
|
+
* emitiéndolos. Quien use otro proveedor de estilo pasa los suyos.
|
|
37
|
+
*/
|
|
38
|
+
readonly anclas?: Anclas;
|
|
39
|
+
readonly colores?: Partial<PaletaDelMapa>;
|
|
40
|
+
readonly margenes?: Margenes;
|
|
41
|
+
readonly radioDeImprecisionEnMetros?: number;
|
|
42
|
+
/** Hasta dónde se deja navegar. Normalmente, la caja de la región del manifiesto. */
|
|
43
|
+
readonly cajaMaxima?: Caja;
|
|
44
|
+
readonly simbolos?: readonly SimboloDeMapa[];
|
|
45
|
+
/**
|
|
46
|
+
* `true` si el motor ya nació con el estilo que produce `estilo(...)`.
|
|
47
|
+
*
|
|
48
|
+
* Lo usa `crearMapa` de la subruta del navegador, que construye el mapa de
|
|
49
|
+
* MapLibre con el estilo ya calculado. Sin esta bandera el SDK lo pondría
|
|
50
|
+
* otra vez en el constructor: MapLibre avisa por consola —«Style is not
|
|
51
|
+
* done loading, rebuilding from scratch»— y vuelve a descargar los glifos,
|
|
52
|
+
* que son la petición más pesada de la primera pintura.
|
|
53
|
+
*
|
|
54
|
+
* No es una opción para las superficies: es el cable entre las dos mitades
|
|
55
|
+
* de la construcción.
|
|
56
|
+
*/
|
|
57
|
+
readonly estiloYaAplicado?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** Qué encuadrar. */
|
|
60
|
+
export type QueEncuadrar = Caja | readonly Coordenada[] | "todo" | "grupos" | "negocios" | "rutas" | "zonas";
|
|
61
|
+
export interface OpcionesDeSeleccion {
|
|
62
|
+
/**
|
|
63
|
+
* Si seleccionar además emite `negocio:clic`. **Por defecto no**, y esa es
|
|
64
|
+
* la decisión que rompe el bucle lista↔mapa.
|
|
65
|
+
*
|
|
66
|
+
* La pantalla de resultados escucha `negocio:clic` para abrir la ficha. Si
|
|
67
|
+
* `seleccionarNegocio` lo emitiera, tocar un resultado en la lista abriría
|
|
68
|
+
* la ficha dos veces: una por el toque en la lista y otra por el eco del
|
|
69
|
+
* mapa. Quien de verdad quiera el eco lo pide.
|
|
70
|
+
*/
|
|
71
|
+
readonly emitirEvento?: boolean;
|
|
72
|
+
/** Si además se lleva la cámara al negocio. Por defecto no. */
|
|
73
|
+
readonly encuadrar?: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface MapaDeCerca {
|
|
76
|
+
ponerResultados(resultados: ResultadosEnMapa): void;
|
|
77
|
+
ponerNegocios(negocios: readonly NegocioEnMapa[]): void;
|
|
78
|
+
seleccionarNegocio(id: string | undefined, opciones?: OpcionesDeSeleccion): void;
|
|
79
|
+
ponerUbicacionDeUsuario(ubicacion: UbicacionDeUsuarioEnMapa | undefined): void;
|
|
80
|
+
ponerVehiculos(vehiculos: readonly VehiculoEnMapa[]): void;
|
|
81
|
+
moverVehiculo(id: string, ubicacion: Coordenada, rumbo?: number): void;
|
|
82
|
+
mostrarRuta(rutas: readonly RutaEnMapa[]): void;
|
|
83
|
+
mostrarZonaDeCobertura(zonas: readonly ZonaEnMapa[]): void;
|
|
84
|
+
mostrarIsocrona(bandas: readonly BandaDeIsocrona[]): void;
|
|
85
|
+
encuadrar(que?: QueEncuadrar, opciones?: Partial<OpcionesDeEncuadre>): void;
|
|
86
|
+
volarA(destino: DestinoDeCamara, opciones?: Partial<OpcionesDeMovimiento>): void;
|
|
87
|
+
vista(): ReturnType<MapaNativo["vista"]>;
|
|
88
|
+
proyectar(coordenada: Coordenada): PuntoEnPantalla;
|
|
89
|
+
desproyectar(punto: PuntoEnPantalla): Coordenada;
|
|
90
|
+
queHayEn(punto: PuntoEnPantalla, capas?: readonly string[]): readonly EntidadDibujada[];
|
|
91
|
+
ponerTema(tema: Tema): void;
|
|
92
|
+
ponerIdioma(idioma: string): void;
|
|
93
|
+
registrarSimbolos(simbolos: readonly SimboloDeMapa[]): void;
|
|
94
|
+
ponerMargenes(margenes: Margenes): void;
|
|
95
|
+
agregarCapaExtra(extra: CapaExtra): Desuscribir;
|
|
96
|
+
cuando<T extends TipoDeEvento>(tipo: T, manejador: (evento: EventosDelMapa[T]) => void): Desuscribir;
|
|
97
|
+
unaVez<T extends TipoDeEvento>(tipo: T, manejador: (evento: EventosDelMapa[T]) => void): Desuscribir;
|
|
98
|
+
destruir(): void;
|
|
99
|
+
estaDestruido(): boolean;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Crea el SDK sobre un motor ya construido.
|
|
103
|
+
*
|
|
104
|
+
* Las superficies no llaman a esto: llaman a `crearMapa` de
|
|
105
|
+
* `@cerca.red/mapa/navegador`, que construye el motor de MapLibre y llama
|
|
106
|
+
* aquí. Esta puerta existe para las pruebas y para cualquier motor futuro.
|
|
107
|
+
*/
|
|
108
|
+
export declare function crearMapaConMotor(motor: MapaNativo, opciones: OpcionesDeCrearMapa): MapaDeCerca;
|
|
109
|
+
/** Reexportado para que quien construya una capa extra vacía no invente la forma. */
|
|
110
|
+
export { coleccionVacia };
|
|
111
|
+
export type { CapaExtra };
|