@elabs-ai/components-maps 4.2.0 → 5.1.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 +1 -1
- package/dist/chunk-2FPB53NG.js +36 -0
- package/dist/chunk-2FPB53NG.js.map +1 -0
- package/dist/chunk-2VVJRT66.js +37 -0
- package/dist/chunk-2VVJRT66.js.map +1 -0
- package/dist/chunk-3HXFONRP.js +2 -0
- package/dist/chunk-3HXFONRP.js.map +1 -0
- package/dist/chunk-3SJN3IYT.js +2 -0
- package/dist/chunk-3SJN3IYT.js.map +1 -0
- package/dist/chunk-4DANBD5B.js +55 -0
- package/dist/chunk-4DANBD5B.js.map +1 -0
- package/dist/chunk-5PDVG53B.js +2 -0
- package/dist/chunk-5PDVG53B.js.map +1 -0
- package/dist/chunk-643R7IJC.js +2 -0
- package/dist/chunk-643R7IJC.js.map +1 -0
- package/dist/chunk-B3ZDBQ6I.js +164 -0
- package/dist/chunk-B3ZDBQ6I.js.map +1 -0
- package/dist/chunk-BGCE3RR5.js +35 -0
- package/dist/chunk-BGCE3RR5.js.map +1 -0
- package/dist/chunk-C4VI37TD.js +485 -0
- package/dist/chunk-C4VI37TD.js.map +1 -0
- package/dist/chunk-CJJT6AEI.js +179 -0
- package/dist/chunk-CJJT6AEI.js.map +1 -0
- package/dist/chunk-D2RCPTRO.js +2 -0
- package/dist/chunk-D2RCPTRO.js.map +1 -0
- package/dist/chunk-DTV7JZVN.js +2 -0
- package/dist/chunk-DTV7JZVN.js.map +1 -0
- package/dist/chunk-E65Z3MSV.js +80 -0
- package/dist/chunk-E65Z3MSV.js.map +1 -0
- package/dist/chunk-E7VPNINZ.js +70 -0
- package/dist/chunk-E7VPNINZ.js.map +1 -0
- package/dist/chunk-FHV5IA6N.js +100 -0
- package/dist/chunk-FHV5IA6N.js.map +1 -0
- package/dist/chunk-FQ6V7BFZ.js +347 -0
- package/dist/chunk-FQ6V7BFZ.js.map +1 -0
- package/dist/chunk-G7JDXDJN.js +19 -0
- package/dist/chunk-G7JDXDJN.js.map +1 -0
- package/dist/chunk-GWULZOMW.js +21 -0
- package/dist/chunk-GWULZOMW.js.map +1 -0
- package/dist/chunk-GYDTTAVD.js +120 -0
- package/dist/chunk-GYDTTAVD.js.map +1 -0
- package/dist/chunk-HCOBWIM4.js +48 -0
- package/dist/chunk-HCOBWIM4.js.map +1 -0
- package/dist/chunk-IAHK5MVT.js +2 -0
- package/dist/chunk-IAHK5MVT.js.map +1 -0
- package/dist/chunk-JGJ6442I.js +235 -0
- package/dist/chunk-JGJ6442I.js.map +1 -0
- package/dist/chunk-JYFERXZT.js +18 -0
- package/dist/chunk-JYFERXZT.js.map +1 -0
- package/dist/chunk-LU2UEKFM.js +53 -0
- package/dist/chunk-LU2UEKFM.js.map +1 -0
- package/dist/chunk-LVYM6C5C.js +2 -0
- package/dist/chunk-LVYM6C5C.js.map +1 -0
- package/dist/chunk-MIMDP3EU.js +104 -0
- package/dist/chunk-MIMDP3EU.js.map +1 -0
- package/dist/chunk-NNBURJHY.js +2 -0
- package/dist/chunk-NNBURJHY.js.map +1 -0
- package/dist/chunk-NPUC3V37.js +2 -0
- package/dist/chunk-NPUC3V37.js.map +1 -0
- package/dist/chunk-OEVVNPN3.js +201 -0
- package/dist/chunk-OEVVNPN3.js.map +1 -0
- package/dist/chunk-PF3R2BXM.js +200 -0
- package/dist/chunk-PF3R2BXM.js.map +1 -0
- package/dist/chunk-Q2I5YODW.js +2 -0
- package/dist/chunk-Q2I5YODW.js.map +1 -0
- package/dist/chunk-QDWWP3N7.js +247 -0
- package/dist/chunk-QDWWP3N7.js.map +1 -0
- package/dist/chunk-QU33KPMP.js +2 -0
- package/dist/chunk-QU33KPMP.js.map +1 -0
- package/dist/chunk-RK4BUMHS.js +2 -0
- package/dist/chunk-RK4BUMHS.js.map +1 -0
- package/dist/chunk-RNSLG64F.js +26 -0
- package/dist/chunk-RNSLG64F.js.map +1 -0
- package/dist/chunk-RV673TB4.js +68 -0
- package/dist/chunk-RV673TB4.js.map +1 -0
- package/dist/chunk-S7N2WMVT.js +180 -0
- package/dist/chunk-S7N2WMVT.js.map +1 -0
- package/dist/chunk-T3Z6TCDD.js +2 -0
- package/dist/chunk-T3Z6TCDD.js.map +1 -0
- package/dist/chunk-T4TJTVVA.js +105 -0
- package/dist/chunk-T4TJTVVA.js.map +1 -0
- package/dist/chunk-UMOYRCDX.js +103 -0
- package/dist/chunk-UMOYRCDX.js.map +1 -0
- package/dist/chunk-V2REM6UT.js +185 -0
- package/dist/chunk-V2REM6UT.js.map +1 -0
- package/dist/chunk-VFBRFGID.js +89 -0
- package/dist/chunk-VFBRFGID.js.map +1 -0
- package/dist/chunk-W76NLFER.js +103 -0
- package/dist/chunk-W76NLFER.js.map +1 -0
- package/dist/chunk-WNU4IOGL.js +116 -0
- package/dist/chunk-WNU4IOGL.js.map +1 -0
- package/dist/chunk-WS4Z7ENS.js +494 -0
- package/dist/chunk-WS4Z7ENS.js.map +1 -0
- package/dist/chunk-XQT7YLJY.js +497 -0
- package/dist/chunk-XQT7YLJY.js.map +1 -0
- package/dist/chunk-Y44MEKJV.js +21 -0
- package/dist/chunk-Y44MEKJV.js.map +1 -0
- package/dist/chunk-Z4EPSOB4.js +53 -0
- package/dist/chunk-Z4EPSOB4.js.map +1 -0
- package/dist/chunk-Z5OPDBDC.js +2 -0
- package/dist/chunk-Z5OPDBDC.js.map +1 -0
- package/dist/index.d.ts +1241 -46
- package/dist/index.js +189 -1471
- package/dist/index.js.map +1 -1
- package/dist/lib/arc-math.js +8 -0
- package/dist/lib/arc-math.js.map +1 -0
- package/dist/lib/map-position.js +11 -0
- package/dist/lib/map-position.js.map +1 -0
- package/dist/lib/merge-hover-paint.js +10 -0
- package/dist/lib/merge-hover-paint.js.map +1 -0
- package/dist/lib/plan-crs.js +14 -0
- package/dist/lib/plan-crs.js.map +1 -0
- package/dist/lib/plan-patterns.js +14 -0
- package/dist/lib/plan-patterns.js.map +1 -0
- package/dist/lib/plan-regions.js +18 -0
- package/dist/lib/plan-regions.js.map +1 -0
- package/dist/lib/plan-status.js +14 -0
- package/dist/lib/plan-status.js.map +1 -0
- package/dist/lib/route-arrow.js +12 -0
- package/dist/lib/route-arrow.js.map +1 -0
- package/dist/lib/use-map-breakpoint.js +33 -0
- package/dist/lib/use-map-breakpoint.js.map +1 -0
- package/dist/lib/use-plan-projection.js +9 -0
- package/dist/lib/use-plan-projection.js.map +1 -0
- package/dist/lib/use-token-color.js +10 -0
- package/dist/lib/use-token-color.js.map +1 -0
- package/dist/lib/warn-once.js +10 -0
- package/dist/lib/warn-once.js.map +1 -0
- package/dist/map-annotation/anchor.js +14 -0
- package/dist/map-annotation/anchor.js.map +1 -0
- package/dist/map-annotation/index.js +21 -0
- package/dist/map-annotation/index.js.map +1 -0
- package/dist/map-annotation/map-annotation.js +18 -0
- package/dist/map-annotation/map-annotation.js.map +1 -0
- package/dist/map-arc/index.js +16 -0
- package/dist/map-arc/index.js.map +1 -0
- package/dist/map-arc/map-arc.js +13 -0
- package/dist/map-arc/map-arc.js.map +1 -0
- package/dist/map-canvas/index.css +11 -0
- package/dist/map-canvas/index.css.map +1 -0
- package/dist/map-canvas/index.js +20 -0
- package/dist/map-canvas/index.js.map +1 -0
- package/dist/map-canvas/map-canvas.css +11 -0
- package/dist/map-canvas/map-canvas.css.map +1 -0
- package/dist/map-canvas/map-canvas.js +17 -0
- package/dist/map-canvas/map-canvas.js.map +1 -0
- package/dist/map-canvas/map-context.js +11 -0
- package/dist/map-canvas/map-context.js.map +1 -0
- package/dist/map-canvas/use-resolved-basemap-theme.js +9 -0
- package/dist/map-canvas/use-resolved-basemap-theme.js.map +1 -0
- package/dist/map-cluster-layer/index.js +12 -0
- package/dist/map-cluster-layer/index.js.map +1 -0
- package/dist/map-cluster-layer/map-cluster-layer.js +12 -0
- package/dist/map-cluster-layer/map-cluster-layer.js.map +1 -0
- package/dist/map-controls/index.js +11 -0
- package/dist/map-controls/index.js.map +1 -0
- package/dist/map-controls/map-controls.js +11 -0
- package/dist/map-controls/map-controls.js.map +1 -0
- package/dist/map-geojson/index.js +13 -0
- package/dist/map-geojson/index.js.map +1 -0
- package/dist/map-geojson/map-geojson.js +13 -0
- package/dist/map-geojson/map-geojson.js.map +1 -0
- package/dist/map-inset/index.css +11 -0
- package/dist/map-inset/index.css.map +1 -0
- package/dist/map-inset/index.js +20 -0
- package/dist/map-inset/index.js.map +1 -0
- package/dist/map-inset/map-inset.css +11 -0
- package/dist/map-inset/map-inset.css.map +1 -0
- package/dist/map-inset/map-inset.js +20 -0
- package/dist/map-inset/map-inset.js.map +1 -0
- package/dist/map-legend/index.js +14 -0
- package/dist/map-legend/index.js.map +1 -0
- package/dist/map-legend/map-corner.js +10 -0
- package/dist/map-legend/map-corner.js.map +1 -0
- package/dist/map-legend/map-legend.js +11 -0
- package/dist/map-legend/map-legend.js.map +1 -0
- package/dist/map-marker/index.js +22 -0
- package/dist/map-marker/index.js.map +1 -0
- package/dist/map-marker/map-marker.js +22 -0
- package/dist/map-marker/map-marker.js.map +1 -0
- package/dist/map-north-arrow/index.js +11 -0
- package/dist/map-north-arrow/index.js.map +1 -0
- package/dist/map-north-arrow/map-north-arrow.js +11 -0
- package/dist/map-north-arrow/map-north-arrow.js.map +1 -0
- package/dist/map-plan/index.js +30 -0
- package/dist/map-plan/index.js.map +1 -0
- package/dist/map-plan/map-plan-legend.js +10 -0
- package/dist/map-plan/map-plan-legend.js.map +1 -0
- package/dist/map-plan/map-plan-overlay.js +13 -0
- package/dist/map-plan/map-plan-overlay.js.map +1 -0
- package/dist/map-plan/map-plan-status.js +9 -0
- package/dist/map-plan/map-plan-status.js.map +1 -0
- package/dist/map-plan/map-plan-table.js +10 -0
- package/dist/map-plan/map-plan-table.js.map +1 -0
- package/dist/map-plan/use-plan-selection.js +9 -0
- package/dist/map-plan/use-plan-selection.js.map +1 -0
- package/dist/map-plan-image/index.js +11 -0
- package/dist/map-plan-image/index.js.map +1 -0
- package/dist/map-plan-image/map-plan-image.js +11 -0
- package/dist/map-plan-image/map-plan-image.js.map +1 -0
- package/dist/map-popup/index.js +12 -0
- package/dist/map-popup/index.js.map +1 -0
- package/dist/map-popup/map-popup.js +12 -0
- package/dist/map-popup/map-popup.js.map +1 -0
- package/dist/map-route/index.js +12 -0
- package/dist/map-route/index.js.map +1 -0
- package/dist/map-route/map-route.js +12 -0
- package/dist/map-route/map-route.js.map +1 -0
- package/dist/map-scale-bar/index.js +18 -0
- package/dist/map-scale-bar/index.js.map +1 -0
- package/dist/map-scale-bar/map-scale-bar.js +18 -0
- package/dist/map-scale-bar/map-scale-bar.js.map +1 -0
- package/package.json +5 -5
- package/src/index.ts +83 -0
- package/src/lib/arc-math.test.ts +19 -0
- package/src/lib/arc-math.ts +6 -1
- package/src/lib/map-position.ts +77 -0
- package/src/lib/merge-hover-paint.ts +44 -13
- package/src/lib/plan-crs.parity.test.ts +39 -0
- package/src/lib/plan-crs.test.ts +248 -0
- package/src/lib/plan-crs.ts +252 -0
- package/src/lib/plan-patterns.test.ts +255 -0
- package/src/lib/plan-patterns.ts +160 -0
- package/src/lib/plan-regions.test.ts +186 -0
- package/src/lib/plan-regions.ts +209 -0
- package/src/lib/plan-status.test.ts +87 -0
- package/src/lib/plan-status.ts +147 -0
- package/src/lib/route-arrow.test.ts +88 -0
- package/src/lib/route-arrow.ts +59 -0
- package/src/lib/use-map-breakpoint.test.ts +83 -0
- package/src/lib/use-map-breakpoint.ts +238 -0
- package/src/lib/use-plan-projection.ts +157 -0
- package/src/lib/warn-once.ts +21 -0
- package/src/map-annotation/anchor.ts +92 -0
- package/src/map-annotation/index.ts +15 -0
- package/src/map-annotation/map-annotation.stories.tsx +113 -0
- package/src/map-annotation/map-annotation.test.tsx +106 -0
- package/src/map-annotation/map-annotation.tsx +356 -0
- package/src/map-arc/map-arc.tsx +26 -5
- package/src/map-canvas/map-canvas.stories.tsx +211 -0
- package/src/map-canvas/map-canvas.test.tsx +389 -0
- package/src/map-canvas/map-canvas.tsx +457 -17
- package/src/map-canvas/map-context.ts +11 -0
- package/src/map-cluster-layer/map-cluster-layer.tsx +14 -1
- package/src/map-controls/map-controls.stories.tsx +16 -0
- package/src/map-controls/map-controls.test.tsx +145 -1
- package/src/map-controls/map-controls.tsx +57 -12
- package/src/map-geojson/map-geojson.stories.tsx +153 -3
- package/src/map-geojson/map-geojson.test.tsx +453 -0
- package/src/map-geojson/map-geojson.tsx +591 -51
- package/src/map-inset/index.ts +1 -0
- package/src/map-inset/map-inset.stories.tsx +61 -0
- package/src/map-inset/map-inset.test.tsx +117 -0
- package/src/map-inset/map-inset.tsx +264 -0
- package/src/map-legend/index.ts +10 -0
- package/src/map-legend/map-corner.ts +23 -0
- package/src/map-legend/map-legend.stories.tsx +171 -0
- package/src/map-legend/map-legend.test.tsx +136 -0
- package/src/map-legend/map-legend.tsx +264 -0
- package/src/map-marker/map-marker.stories.tsx +136 -4
- package/src/map-marker/map-marker.test.tsx +328 -3
- package/src/map-marker/map-marker.tsx +370 -33
- package/src/map-north-arrow/index.ts +1 -0
- package/src/map-north-arrow/map-north-arrow.stories.tsx +65 -0
- package/src/map-north-arrow/map-north-arrow.test.tsx +39 -0
- package/src/map-north-arrow/map-north-arrow.tsx +82 -0
- package/src/map-plan/index.ts +13 -0
- package/src/map-plan/map-plan-legend.test.tsx +61 -0
- package/src/map-plan/map-plan-legend.tsx +83 -0
- package/src/map-plan/map-plan-overlay.stories.tsx +260 -0
- package/src/map-plan/map-plan-overlay.test.tsx +302 -0
- package/src/map-plan/map-plan-overlay.tsx +531 -0
- package/src/map-plan/map-plan-status.test.tsx +71 -0
- package/src/map-plan/map-plan-status.tsx +77 -0
- package/src/map-plan/map-plan-table.test.tsx +86 -0
- package/src/map-plan/map-plan-table.tsx +153 -0
- package/src/map-plan/use-plan-selection.ts +78 -0
- package/src/map-plan-image/index.ts +1 -0
- package/src/map-plan-image/map-plan-image.stories.tsx +301 -0
- package/src/map-plan-image/map-plan-image.test.tsx +176 -0
- package/src/map-plan-image/map-plan-image.tsx +279 -0
- package/src/map-popup/map-popup.tsx +15 -10
- package/src/map-route/index.ts +1 -1
- package/src/map-route/map-route.test.tsx +216 -0
- package/src/map-route/map-route.tsx +105 -6
- package/src/map-scale-bar/index.ts +9 -0
- package/src/map-scale-bar/map-scale-bar.stories.tsx +63 -0
- package/src/map-scale-bar/map-scale-bar.test.tsx +65 -0
- package/src/map-scale-bar/map-scale-bar.tsx +145 -0
- package/src/test-utils/locator-fixture.ts +75 -0
- package/src/test-utils/maplibre-mock.ts +256 -19
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A hand-simplified Lake Ontario locator fixture (≈ 20 vertices a shape, WGS 84
|
|
3
|
+
* lon / lat) for the locator-furniture stories and tests — two area markers
|
|
4
|
+
* and a few places. Offline and tiny on purpose; not survey-accurate.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const LAKE_ONTARIO: GeoJSON.Feature<GeoJSON.Polygon, { name: string }> = {
|
|
8
|
+
type: "Feature",
|
|
9
|
+
properties: { name: "Lake Ontario" },
|
|
10
|
+
geometry: {
|
|
11
|
+
type: "Polygon",
|
|
12
|
+
coordinates: [
|
|
13
|
+
[
|
|
14
|
+
[-79.8, 43.28],
|
|
15
|
+
[-79.55, 43.47],
|
|
16
|
+
[-79.38, 43.63],
|
|
17
|
+
[-79.05, 43.78],
|
|
18
|
+
[-78.86, 43.87],
|
|
19
|
+
[-78.17, 43.95],
|
|
20
|
+
[-77.55, 43.99],
|
|
21
|
+
[-77.15, 43.86],
|
|
22
|
+
[-76.82, 43.95],
|
|
23
|
+
[-76.48, 44.21],
|
|
24
|
+
[-76.24, 44.19],
|
|
25
|
+
[-76.2, 43.95],
|
|
26
|
+
[-76.46, 43.52],
|
|
27
|
+
[-76.95, 43.28],
|
|
28
|
+
[-77.6, 43.26],
|
|
29
|
+
[-78.3, 43.37],
|
|
30
|
+
[-78.9, 43.33],
|
|
31
|
+
[-79.06, 43.26],
|
|
32
|
+
[-79.56, 43.2],
|
|
33
|
+
[-79.8, 43.28],
|
|
34
|
+
],
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const GREATER_TORONTO: GeoJSON.Feature<GeoJSON.Polygon, { name: string }> = {
|
|
40
|
+
type: "Feature",
|
|
41
|
+
properties: { name: "Greater Toronto Area" },
|
|
42
|
+
geometry: {
|
|
43
|
+
type: "Polygon",
|
|
44
|
+
coordinates: [
|
|
45
|
+
[
|
|
46
|
+
[-79.8, 43.3],
|
|
47
|
+
[-79.55, 43.47],
|
|
48
|
+
[-79.38, 43.63],
|
|
49
|
+
[-79.05, 43.78],
|
|
50
|
+
[-78.86, 43.87],
|
|
51
|
+
[-78.8, 44.15],
|
|
52
|
+
[-79.3, 44.28],
|
|
53
|
+
[-79.85, 44.08],
|
|
54
|
+
[-80.05, 43.72],
|
|
55
|
+
[-79.8, 43.3],
|
|
56
|
+
],
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/** West, south, east, north of both areas — the locator's data extent. */
|
|
62
|
+
export const LOCATOR_BOUNDS: [[number, number], [number, number]] = [
|
|
63
|
+
[-80.05, 43.2],
|
|
64
|
+
[-76.2, 44.28],
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
/** Places the locator labels, west → east. */
|
|
68
|
+
export const LOCATOR_PLACES = {
|
|
69
|
+
toronto: { longitude: -79.38, latitude: 43.65 },
|
|
70
|
+
hamilton: { longitude: -79.87, latitude: 43.25 },
|
|
71
|
+
rochester: { longitude: -77.61, latitude: 43.16 },
|
|
72
|
+
kingston: { longitude: -76.48, latitude: 44.23 },
|
|
73
|
+
lakeLabel: { longitude: -77.9, latitude: 43.62 },
|
|
74
|
+
gtaLabel: { longitude: -79.45, latitude: 43.93 },
|
|
75
|
+
} as const;
|
|
@@ -13,16 +13,112 @@
|
|
|
13
13
|
|
|
14
14
|
type Handler = (...args: any[]) => void;
|
|
15
15
|
|
|
16
|
+
export class MockHandler {
|
|
17
|
+
enabled = true;
|
|
18
|
+
enable() {
|
|
19
|
+
this.enabled = true;
|
|
20
|
+
}
|
|
21
|
+
disable() {
|
|
22
|
+
this.enabled = false;
|
|
23
|
+
}
|
|
24
|
+
isEnabled() {
|
|
25
|
+
return this.enabled;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* One persistent instance per source id, so a component that subscribes to its
|
|
31
|
+
* own source (`source.on("error", …)`) or updates it in place
|
|
32
|
+
* (`setCoordinates`/`updateImage`) can be asserted against. The spec fields are
|
|
33
|
+
* spread onto the instance, so reads like `source.type` still work.
|
|
34
|
+
*/
|
|
35
|
+
export class MockSource {
|
|
36
|
+
static instances: MockSource[] = [];
|
|
37
|
+
|
|
38
|
+
id: string;
|
|
39
|
+
spec: Record<string, any>;
|
|
40
|
+
handlers = new Map<string, Set<Handler>>();
|
|
41
|
+
setDataCalls: unknown[] = [];
|
|
42
|
+
coordinatesCalls: unknown[] = [];
|
|
43
|
+
updateImageCalls: unknown[] = [];
|
|
44
|
+
|
|
45
|
+
constructor(id: string, spec: Record<string, any>) {
|
|
46
|
+
this.id = id;
|
|
47
|
+
this.spec = spec;
|
|
48
|
+
Object.assign(this, spec);
|
|
49
|
+
MockSource.instances.push(this);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setData(data: unknown) {
|
|
53
|
+
this.setDataCalls.push(data);
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
setCoordinates(coordinates: unknown) {
|
|
57
|
+
this.coordinatesCalls.push(coordinates);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
updateImage(options: unknown) {
|
|
61
|
+
this.updateImageCalls.push(options);
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
async getClusterExpansionZoom() {
|
|
65
|
+
return 2;
|
|
66
|
+
}
|
|
67
|
+
on(event: string, handler: Handler) {
|
|
68
|
+
if (!this.handlers.has(event)) this.handlers.set(event, new Set());
|
|
69
|
+
this.handlers.get(event)!.add(handler);
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
off(event: string, handler: Handler) {
|
|
73
|
+
this.handlers.get(event)?.delete(handler);
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
/** Fire an event on this source — e.g. a failed image fetch. */
|
|
77
|
+
emit(event: string, ...args: unknown[]) {
|
|
78
|
+
this.handlers.get(event)?.forEach((handler) => {
|
|
79
|
+
handler(...args);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
16
84
|
export class MockMap {
|
|
17
85
|
static instances: MockMap[] = [];
|
|
18
86
|
|
|
19
87
|
handlers = new Map<string, Set<Handler>>();
|
|
20
88
|
container: HTMLElement;
|
|
21
89
|
removed = false;
|
|
22
|
-
sources = new Map<string,
|
|
90
|
+
sources = new Map<string, MockSource>();
|
|
23
91
|
layers = new Map<string, any>();
|
|
24
92
|
canvas = document.createElement("canvas");
|
|
93
|
+
/** Starts with MapLibre's interactive class, as a real interactive map's does. */
|
|
94
|
+
canvasContainer = Object.assign(document.createElement("div"), {
|
|
95
|
+
className: "maplibregl-canvas-container maplibregl-interactive",
|
|
96
|
+
});
|
|
25
97
|
zoomToCalls: unknown[] = [];
|
|
98
|
+
images = new Map<string, unknown>();
|
|
99
|
+
center = { lng: 0, lat: 0 };
|
|
100
|
+
zoom = 1;
|
|
101
|
+
bearing = 0;
|
|
102
|
+
|
|
103
|
+
/** Gesture handlers, each with an `enabled` flag static mode flips. */
|
|
104
|
+
scrollZoom = new MockHandler();
|
|
105
|
+
boxZoom = new MockHandler();
|
|
106
|
+
dragRotate = new MockHandler();
|
|
107
|
+
dragPan = new MockHandler();
|
|
108
|
+
keyboard = new MockHandler();
|
|
109
|
+
doubleClickZoom = new MockHandler();
|
|
110
|
+
touchZoomRotate = new MockHandler();
|
|
111
|
+
touchPitch = new MockHandler();
|
|
112
|
+
addLayerCalls: unknown[] = [];
|
|
113
|
+
paint = new Map<string, unknown>();
|
|
114
|
+
layout = new Map<string, unknown>();
|
|
115
|
+
featureStateCalls: unknown[] = [];
|
|
116
|
+
/** `[id, image, options]` per `addImage` — the pattern registration asserts `pixelRatio`. */
|
|
117
|
+
addImageCalls: [string, unknown, unknown][] = [];
|
|
118
|
+
updateImageCalls: [string, unknown][] = [];
|
|
119
|
+
minZoom: number | undefined;
|
|
120
|
+
maxZoom: number | undefined;
|
|
121
|
+
maxBounds: unknown;
|
|
26
122
|
|
|
27
123
|
/** The full options object the component constructed the map with. */
|
|
28
124
|
options: Record<string, any>;
|
|
@@ -30,6 +126,10 @@ export class MockMap {
|
|
|
30
126
|
constructor(options: { container: HTMLElement } & Record<string, any>) {
|
|
31
127
|
this.container = options.container;
|
|
32
128
|
this.options = options;
|
|
129
|
+
// What MapLibre would measure: the box's height rule at construction time,
|
|
130
|
+
// and whether that rule could still be mid-transition when it measured.
|
|
131
|
+
this.aspectAtConstruction = options.container.style.aspectRatio;
|
|
132
|
+
this.transitionAtConstruction = options.container.style.transitionProperty;
|
|
33
133
|
MockMap.instances.push(this);
|
|
34
134
|
}
|
|
35
135
|
|
|
@@ -67,13 +167,35 @@ export class MockMap {
|
|
|
67
167
|
}
|
|
68
168
|
|
|
69
169
|
getCenter() {
|
|
70
|
-
return
|
|
170
|
+
return this.center;
|
|
71
171
|
}
|
|
72
172
|
getZoom() {
|
|
73
|
-
return
|
|
173
|
+
return this.zoom;
|
|
74
174
|
}
|
|
75
175
|
getBearing() {
|
|
76
|
-
return
|
|
176
|
+
return this.bearing;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A flat equirectangular stand-in: 1° = 10 px from the container's top-left.
|
|
180
|
+
* Accepts both shapes MapLibre's own `project` does — a `[lng, lat]` pair
|
|
181
|
+
* and a `LngLat`.
|
|
182
|
+
*/
|
|
183
|
+
project(lngLat: [number, number] | { lng: number; lat: number }) {
|
|
184
|
+
const [lng, lat] = Array.isArray(lngLat) ? lngLat : [lngLat.lng, lngLat.lat];
|
|
185
|
+
return { x: (lng + 180) * 10, y: (90 - lat) * 10 };
|
|
186
|
+
}
|
|
187
|
+
/** Inverse of {@link project} — the same flat equirectangular stand-in. */
|
|
188
|
+
unproject(point: [number, number] | { x: number; y: number }) {
|
|
189
|
+
const [x, y] = Array.isArray(point) ? point : [point.x, point.y];
|
|
190
|
+
return { lng: x / 10 - 180, lat: 90 - y / 10 };
|
|
191
|
+
}
|
|
192
|
+
getBounds() {
|
|
193
|
+
return {
|
|
194
|
+
getWest: () => -10,
|
|
195
|
+
getSouth: () => -10,
|
|
196
|
+
getEast: () => 10,
|
|
197
|
+
getNorth: () => 10,
|
|
198
|
+
};
|
|
77
199
|
}
|
|
78
200
|
getPitch() {
|
|
79
201
|
return 0;
|
|
@@ -81,9 +203,19 @@ export class MockMap {
|
|
|
81
203
|
isMoving() {
|
|
82
204
|
return false;
|
|
83
205
|
}
|
|
84
|
-
jumpTo()
|
|
206
|
+
/** Every `jumpTo(options)` the wrapper asked for, in order. */
|
|
207
|
+
jumpToCalls: any[] = [];
|
|
208
|
+
jumpTo(options?: any) {
|
|
209
|
+
this.jumpToCalls.push(options);
|
|
210
|
+
}
|
|
85
211
|
easeTo() {}
|
|
86
212
|
flyTo() {}
|
|
213
|
+
/** Every `fitBounds(bounds, options)` the wrapper asked for, in order. */
|
|
214
|
+
fitBoundsCalls: { bounds: unknown; options: unknown }[] = [];
|
|
215
|
+
fitBounds(bounds: unknown, options?: unknown) {
|
|
216
|
+
this.fitBoundsCalls.push({ bounds, options });
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
87
219
|
zoomTo(zoom: number, options?: unknown) {
|
|
88
220
|
this.zoomToCalls.push([zoom, options]);
|
|
89
221
|
}
|
|
@@ -96,19 +228,39 @@ export class MockMap {
|
|
|
96
228
|
getCanvas() {
|
|
97
229
|
return this.canvas;
|
|
98
230
|
}
|
|
231
|
+
aspectAtConstruction = "";
|
|
232
|
+
transitionAtConstruction = "";
|
|
233
|
+
resizeCount = 0;
|
|
234
|
+
resize() {
|
|
235
|
+
this.resizeCount += 1;
|
|
236
|
+
return this;
|
|
237
|
+
}
|
|
238
|
+
getCanvasContainer() {
|
|
239
|
+
return this.canvasContainer;
|
|
240
|
+
}
|
|
241
|
+
/** `[id, image, options]` per call — the pattern registration asserts `pixelRatio`. */
|
|
242
|
+
addImage(id: string, image: unknown, options?: unknown) {
|
|
243
|
+
this.addImageCalls.push([id, image, options]);
|
|
244
|
+
this.images.set(id, image);
|
|
245
|
+
}
|
|
246
|
+
hasImage(id: string) {
|
|
247
|
+
return this.images.has(id);
|
|
248
|
+
}
|
|
249
|
+
removeImage(id: string) {
|
|
250
|
+
this.images.delete(id);
|
|
251
|
+
}
|
|
99
252
|
addSource(id: string, source: any) {
|
|
100
|
-
this.sources.set(id, source);
|
|
253
|
+
this.sources.set(id, new MockSource(id, source));
|
|
101
254
|
}
|
|
102
255
|
getSource(id: string) {
|
|
103
|
-
|
|
104
|
-
if (!source) return undefined;
|
|
105
|
-
return { ...source, setData: () => {}, getClusterExpansionZoom: async () => 2 };
|
|
256
|
+
return this.sources.get(id);
|
|
106
257
|
}
|
|
107
258
|
removeSource(id: string) {
|
|
108
259
|
this.sources.delete(id);
|
|
109
260
|
}
|
|
110
|
-
addLayer(layer: { id: string }) {
|
|
261
|
+
addLayer(layer: { id: string } & Record<string, any>, beforeId?: string) {
|
|
111
262
|
this.layers.set(layer.id, layer);
|
|
263
|
+
this.addLayerCalls.push([layer, beforeId]);
|
|
112
264
|
}
|
|
113
265
|
getLayer(id: string) {
|
|
114
266
|
return this.layers.get(id);
|
|
@@ -116,11 +268,55 @@ export class MockMap {
|
|
|
116
268
|
removeLayer(id: string) {
|
|
117
269
|
this.layers.delete(id);
|
|
118
270
|
}
|
|
119
|
-
setPaintProperty() {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
271
|
+
setPaintProperty(layerId: string, name: string, value: unknown) {
|
|
272
|
+
this.paint.set(`${layerId}:${name}`, value);
|
|
273
|
+
}
|
|
274
|
+
/** Layout properties the wrapper set, keyed `<layerId>:<property>`. */
|
|
275
|
+
layoutProperties = new Map<string, unknown>();
|
|
276
|
+
setLayoutProperty(layerId: string, property: string, value: unknown) {
|
|
277
|
+
this.layoutProperties.set(`${layerId}:${property}`, value);
|
|
278
|
+
this.layout.set(`${layerId}:${property}`, value);
|
|
279
|
+
}
|
|
280
|
+
getLayoutProperty(layerId: string, property: string) {
|
|
281
|
+
return this.layoutProperties.get(`${layerId}:${property}`);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The style the map is showing. Like MapLibre's own, it lists every layer
|
|
285
|
+
* the map holds — a test describes a basemap's symbol layers by adding them
|
|
286
|
+
* with `addLayer`.
|
|
287
|
+
*/
|
|
288
|
+
getStyle() {
|
|
289
|
+
return { layers: [...this.layers.values()] };
|
|
290
|
+
}
|
|
291
|
+
/** Observable feature-state, keyed by feature id — the hover highlight. */
|
|
292
|
+
featureStates = new Map<string | number, Record<string, unknown>>();
|
|
293
|
+
setFeatureState(target: { source: string; id: string | number }, state: Record<string, unknown>) {
|
|
294
|
+
this.featureStateCalls.push([target, state]);
|
|
295
|
+
this.featureStates.set(target.id, { ...this.featureStates.get(target.id), ...state });
|
|
296
|
+
}
|
|
297
|
+
/** What the next `queryRenderedFeatures` should return; set it per test. */
|
|
298
|
+
queryRenderedFeaturesResult: any[] = [];
|
|
299
|
+
queryRenderedFeaturesCalls: unknown[] = [];
|
|
300
|
+
queryRenderedFeatures(geometry?: unknown, options?: unknown) {
|
|
301
|
+
this.queryRenderedFeaturesCalls.push([geometry, options]);
|
|
302
|
+
return this.queryRenderedFeaturesResult;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Camera limits — a plan map clamps pan and zoom to its extent.
|
|
306
|
+
setMinZoom(zoom: number) {
|
|
307
|
+
this.minZoom = zoom;
|
|
308
|
+
}
|
|
309
|
+
setMaxZoom(zoom: number) {
|
|
310
|
+
this.maxZoom = zoom;
|
|
311
|
+
}
|
|
312
|
+
setMaxBounds(bounds: unknown) {
|
|
313
|
+
this.maxBounds = bounds;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** A canvas-generated tile re-registered in place, `[id, image]` per call. */
|
|
317
|
+
updateImage(id: string, image: unknown) {
|
|
318
|
+
this.updateImageCalls.push([id, image]);
|
|
319
|
+
this.images.set(id, image);
|
|
124
320
|
}
|
|
125
321
|
}
|
|
126
322
|
|
|
@@ -140,8 +336,11 @@ export class MockMarker {
|
|
|
140
336
|
MockMarker.instances.push(this);
|
|
141
337
|
}
|
|
142
338
|
|
|
143
|
-
|
|
144
|
-
|
|
339
|
+
/** Accepts both shapes MapLibre does: a `[lng, lat]` pair and a `LngLat`. */
|
|
340
|
+
setLngLat(lngLat: [number, number] | { lng: number; lat: number }) {
|
|
341
|
+
this.lngLat = Array.isArray(lngLat)
|
|
342
|
+
? { lng: lngLat[0], lat: lngLat[1] }
|
|
343
|
+
: { lng: lngLat.lng, lat: lngLat.lat };
|
|
145
344
|
return this;
|
|
146
345
|
}
|
|
147
346
|
getLngLat() {
|
|
@@ -203,6 +402,8 @@ export class MockPopup {
|
|
|
203
402
|
static instances: MockPopup[] = [];
|
|
204
403
|
|
|
205
404
|
content: HTMLElement | null = null;
|
|
405
|
+
/** Whether the popup is currently on a map — what `addTo`/`remove` toggle. */
|
|
406
|
+
open = false;
|
|
206
407
|
|
|
207
408
|
constructor() {
|
|
208
409
|
MockPopup.instances.push(this);
|
|
@@ -225,13 +426,15 @@ export class MockPopup {
|
|
|
225
426
|
return this;
|
|
226
427
|
}
|
|
227
428
|
addTo() {
|
|
429
|
+
this.open = true;
|
|
228
430
|
return this;
|
|
229
431
|
}
|
|
230
432
|
remove() {
|
|
433
|
+
this.open = false;
|
|
231
434
|
return this;
|
|
232
435
|
}
|
|
233
436
|
isOpen() {
|
|
234
|
-
return
|
|
437
|
+
return this.open;
|
|
235
438
|
}
|
|
236
439
|
on() {
|
|
237
440
|
return this;
|
|
@@ -241,19 +444,53 @@ export class MockPopup {
|
|
|
241
444
|
}
|
|
242
445
|
}
|
|
243
446
|
|
|
447
|
+
/**
|
|
448
|
+
* The real Web Mercator transform, so a plan coordinate system behaves under
|
|
449
|
+
* test exactly as it does in a browser.
|
|
450
|
+
*/
|
|
451
|
+
export class MockMercatorCoordinate {
|
|
452
|
+
constructor(
|
|
453
|
+
public x: number,
|
|
454
|
+
public y: number,
|
|
455
|
+
public z = 0,
|
|
456
|
+
) {}
|
|
457
|
+
|
|
458
|
+
static fromLngLat(lngLat: { lng: number; lat: number } | [number, number], altitude = 0) {
|
|
459
|
+
const [lng, lat] = Array.isArray(lngLat) ? lngLat : [lngLat.lng, lngLat.lat];
|
|
460
|
+
const x = (180 + lng) / 360;
|
|
461
|
+
const y =
|
|
462
|
+
(180 - (180 / Math.PI) * Math.log(Math.tan(Math.PI / 4 + (lat * Math.PI) / 360))) / 360;
|
|
463
|
+
return new MockMercatorCoordinate(x, y, altitude);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
toLngLat() {
|
|
467
|
+
const lng = this.x * 360 - 180;
|
|
468
|
+
const y2 = 180 - this.y * 360;
|
|
469
|
+
const lat = (360 / Math.PI) * (Math.atan(Math.exp((y2 * Math.PI) / 180)) - Math.PI / 4);
|
|
470
|
+
return { lng, lat };
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
244
474
|
/** Reset the per-class instance registries between tests. */
|
|
245
475
|
export function resetMaplibreMock() {
|
|
246
476
|
MockMap.instances = [];
|
|
247
477
|
MockMarker.instances = [];
|
|
248
478
|
MockPopup.instances = [];
|
|
479
|
+
MockSource.instances = [];
|
|
249
480
|
}
|
|
250
481
|
|
|
251
482
|
/** The module shape to return from `vi.mock("maplibre-gl", ...)`. */
|
|
252
483
|
export function createMaplibreMock() {
|
|
253
484
|
return {
|
|
254
|
-
default: {
|
|
485
|
+
default: {
|
|
486
|
+
Map: MockMap,
|
|
487
|
+
Marker: MockMarker,
|
|
488
|
+
Popup: MockPopup,
|
|
489
|
+
MercatorCoordinate: MockMercatorCoordinate,
|
|
490
|
+
},
|
|
255
491
|
Map: MockMap,
|
|
256
492
|
Marker: MockMarker,
|
|
257
493
|
Popup: MockPopup,
|
|
494
|
+
MercatorCoordinate: MockMercatorCoordinate,
|
|
258
495
|
};
|
|
259
496
|
}
|