@mapka/maplibre-gl-sdk 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/map.ts ADDED
@@ -0,0 +1,43 @@
1
+ import * as maplibregl from "maplibre-gl";
2
+ import type { RequestTransformFunction, MapOptions } from "maplibre-gl";
3
+ import { loadLayersIcons } from "./modules/icons.js";
4
+
5
+ export interface MapkaMapOptions extends MapOptions {
6
+ apiKey: string;
7
+ env?: "dev" | "prod" | "local";
8
+ }
9
+
10
+ const noopTransformRequest: RequestTransformFunction = (url) => {
11
+ return {
12
+ url,
13
+ };
14
+ };
15
+
16
+ const createTransformRequest =
17
+ (apiKey: string, transformRequest?: RequestTransformFunction | null): RequestTransformFunction =>
18
+ (url) => {
19
+ if (url.includes("mapka.dev") || url.includes("mapka.localhost")) {
20
+ return {
21
+ url,
22
+ headers: {
23
+ Authorization: `Bearer ${apiKey}`,
24
+ },
25
+ };
26
+ }
27
+ return transformRequest ? transformRequest(url) : noopTransformRequest(url);
28
+ };
29
+
30
+ export class MapkaMap extends maplibregl.Map {
31
+ static env: string = "prod";
32
+
33
+ public constructor({ transformRequest, apiKey, ...props }: MapkaMapOptions) {
34
+ super({
35
+ ...props,
36
+ transformRequest: createTransformRequest(apiKey, transformRequest),
37
+ });
38
+
39
+ super.on("styleimagemissing", (event: maplibregl.MapStyleImageMissingEvent) => {
40
+ loadLayersIcons(this, event);
41
+ });
42
+ }
43
+ }
@@ -0,0 +1,57 @@
1
+ import { debounce, uniq } from "es-toolkit";
2
+ import { getMapkaUrl } from "../utils/url.js";
3
+ import type { MapkaMap } from "../map.js";
4
+ import type { MapStyleImageMissingEvent } from "maplibre-gl";
5
+
6
+ let missingIcons: string[] = [];
7
+ let loadedIcons: string[] = [];
8
+
9
+ interface Icon {
10
+ id: string;
11
+ svg: string;
12
+ }
13
+
14
+ /**
15
+ * Load missing icons from Mapka API
16
+ * Inspired by https://github.com/mapbox/mapbox-gl-js/issues/5529
17
+ */
18
+ const loadIcons = debounce((map: MapkaMap) => {
19
+ if (missingIcons.length === 0) {
20
+ return;
21
+ }
22
+ const iconsToLoad = uniq(missingIcons).filter((id) => !loadedIcons.includes(id));
23
+ loadedIcons = loadedIcons.concat(iconsToLoad);
24
+ missingIcons = [];
25
+
26
+ if (iconsToLoad.length === 0) {
27
+ return;
28
+ }
29
+
30
+ const search = new URLSearchParams(iconsToLoad.map((id) => ["ids", id]));
31
+ fetch(`${getMapkaUrl()}/v1/icons?${search}`)
32
+ .then((response) => response.json())
33
+ .then((data: Icon[]) => {
34
+ data.forEach(({ svg, id }) => {
35
+ const img = new Image(15, 15);
36
+ img.onload = () => map.addImage(id, img);
37
+ img.src = `data:image/svg+xml;charset=utf-8;base64,${btoa(svg)}`;
38
+ });
39
+ });
40
+ }, 50);
41
+
42
+ /**
43
+ * Load any icons that are missing from the map
44
+ * Only supports icons from Mapka API maki, temaki and tabler
45
+ * @param map
46
+ * @param event
47
+ */
48
+ export function loadLayersIcons(map: MapkaMap, event: MapStyleImageMissingEvent) {
49
+ if (
50
+ event.id.startsWith("maki:") ||
51
+ event.id.startsWith("temaki:") ||
52
+ event.id.startsWith("tabler:")
53
+ ) {
54
+ missingIcons.push(event.id);
55
+ }
56
+ loadIcons(map);
57
+ }
@@ -0,0 +1,12 @@
1
+ import { MapkaMap } from "../map.js";
2
+
3
+ export function getMapkaUrl() {
4
+ console.log("MapkaMap.env", MapkaMap.env);
5
+ if (MapkaMap.env === "dev") {
6
+ return "https://api.dev.mapka.dev";
7
+ }
8
+ if (MapkaMap.env === "local") {
9
+ return "https://api.mapka.localhost";
10
+ }
11
+ return "https://api.mapka.dev";
12
+ }