@mapka/maplibre-gl-sdk 0.12.0 → 0.13.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 +325 -3
- package/lib/.buildInfo.json +1 -1
- package/lib/components/DownloadIcon.d.ts +4 -0
- package/lib/components/DownloadIcon.d.ts.map +1 -0
- package/lib/components/DownloadIcon.js +10 -0
- package/lib/components/PopupContent.d.ts.map +1 -1
- package/lib/components/ProgressDownIcon.d.ts +4 -0
- package/lib/components/ProgressDownIcon.d.ts.map +1 -0
- package/lib/components/ProgressDownIcon.js +14 -0
- package/lib/controls/MapkaExportControl.d.ts +21 -0
- package/lib/controls/MapkaExportControl.d.ts.map +1 -0
- package/lib/controls/MapkaExportControl.js +76 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/map.d.ts +11 -2
- package/lib/map.d.ts.map +1 -1
- package/lib/map.js +10 -5
- package/lib/modules/export.d.ts +4 -0
- package/lib/modules/export.d.ts.map +1 -0
- package/lib/modules/export.js +40 -0
- package/lib/modules/popup.d.ts +2 -2
- package/lib/modules/popup.d.ts.map +1 -1
- package/lib/modules/popup.js +6 -5
- package/lib/types/export.d.ts +7 -0
- package/lib/types/export.d.ts.map +1 -0
- package/lib/types/export.js +1 -0
- package/package.json +3 -2
- package/src/components/DownloadIcon.tsx +25 -0
- package/src/components/PopupContent.tsx +1 -0
- package/src/components/ProgressDownIcon.tsx +29 -0
- package/src/controls/MapkaExportControl.tsx +111 -0
- package/src/index.ts +5 -0
- package/src/map.ts +17 -4
- package/src/modules/export.ts +55 -0
- package/src/modules/popup.tsx +13 -23
- package/src/types/export.ts +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DownloadIcon.d.ts","sourceRoot":"","sources":["../../src/components/DownloadIcon.tsx"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,eAAO,MAAM,YAAY,qBAqBxB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** biome-ignore-all lint/correctness/noUnusedImports: <explanation> */
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
export const DownloadIcon = () => {
|
|
4
|
+
return (h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-label": "Download" },
|
|
5
|
+
h("title", null, "Download"),
|
|
6
|
+
h("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
|
|
7
|
+
h("path", { d: "M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" }),
|
|
8
|
+
h("path", { d: "M7 11l5 5l5 -5" }),
|
|
9
|
+
h("path", { d: "M12 4l0 12" })));
|
|
10
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopupContent.d.ts","sourceRoot":"","sources":["../../src/components/PopupContent.tsx"],"names":[],"mappings":"AAAA,uEAAuE;
|
|
1
|
+
{"version":3,"file":"PopupContent.d.ts","sourceRoot":"","sources":["../../src/components/PopupContent.tsx"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,CAAC,EAAY,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,UAAU,UAAW,SAAQ,iBAAiB;IAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA8LD,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,WAAW,EACX,SAAS,EACT,UAAU,EACV,OAAO,GACR,EAAE,UAAU,iBAqBZ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProgressDownIcon.d.ts","sourceRoot":"","sources":["../../src/components/ProgressDownIcon.tsx"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,eAAO,MAAM,gBAAgB,qBAyB5B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** biome-ignore-all lint/correctness/noUnusedImports: <explanation> */
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
export const ProgressDownIcon = () => {
|
|
4
|
+
return (h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "icon icon-tabler icons-tabler-outline icon-tabler-progress-down" },
|
|
5
|
+
h("title", null, "Progress Download"),
|
|
6
|
+
h("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
|
|
7
|
+
h("path", { d: "M10 20.777a8.942 8.942 0 0 1 -2.48 -.969" }),
|
|
8
|
+
h("path", { d: "M14 3.223a9.003 9.003 0 0 1 0 17.554" }),
|
|
9
|
+
h("path", { d: "M4.579 17.093a8.961 8.961 0 0 1 -1.227 -2.592" }),
|
|
10
|
+
h("path", { d: "M3.124 10.5c.16 -.95 .468 -1.85 .9 -2.675l.169 -.305" }),
|
|
11
|
+
h("path", { d: "M6.907 4.579a8.954 8.954 0 0 1 3.093 -1.356" }),
|
|
12
|
+
h("path", { d: "M12 9v6" }),
|
|
13
|
+
h("path", { d: "M15 12l-3 3l-3 -3" })));
|
|
14
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IControl } from "maplibre-gl";
|
|
2
|
+
import type { MapkaMap } from "../map.js";
|
|
3
|
+
import type { MapkaExportOptions } from "../types/export.js";
|
|
4
|
+
export interface MapkaExportControlOptions extends MapkaExportOptions {
|
|
5
|
+
filename?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class MapkaExportControl implements IControl {
|
|
8
|
+
private map;
|
|
9
|
+
private container;
|
|
10
|
+
private options;
|
|
11
|
+
private isExporting;
|
|
12
|
+
constructor(options?: MapkaExportControlOptions);
|
|
13
|
+
private downloadImage;
|
|
14
|
+
private handleError;
|
|
15
|
+
private onClick;
|
|
16
|
+
private render;
|
|
17
|
+
private unmount;
|
|
18
|
+
onAdd(map: MapkaMap): HTMLElement;
|
|
19
|
+
onRemove(): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=MapkaExportControl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapkaExportControl.d.ts","sourceRoot":"","sources":["../../src/controls/MapkaExportControl.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiBD,qBAAa,kBAAmB,YAAW,QAAQ;IACjD,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,yBAA8B;IAOnD,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,OAAO,CAmBb;IAEF,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;IAQR,KAAK,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW;IAWjC,QAAQ,IAAI,IAAI;CAQxB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// biome-ignore lint/correctness/noUnusedImports: preact jsx
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
import { render } from "preact";
|
|
4
|
+
import { DownloadIcon } from "../components/DownloadIcon.js";
|
|
5
|
+
import { ProgressDownIcon } from "../components/ProgressDownIcon.js";
|
|
6
|
+
const Button = ({ isExporting, onClick }) => {
|
|
7
|
+
return (h("button", { type: "button", className: "maplibregl-ctrl maplibregl-ctrl-group", title: "Export map as PNG", "aria-label": "Export map as PNG", disabled: isExporting, onClick: onClick }, isExporting ? h(ProgressDownIcon, null) : h(DownloadIcon, null)));
|
|
8
|
+
};
|
|
9
|
+
export class MapkaExportControl {
|
|
10
|
+
map;
|
|
11
|
+
container;
|
|
12
|
+
options;
|
|
13
|
+
isExporting = false;
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.options = {
|
|
16
|
+
filename: "map-export",
|
|
17
|
+
...options,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
downloadImage(img) {
|
|
21
|
+
const link = document.createElement("a");
|
|
22
|
+
link.download = `${this.options.filename}.png`;
|
|
23
|
+
link.href = img.src;
|
|
24
|
+
link.click();
|
|
25
|
+
link.remove();
|
|
26
|
+
}
|
|
27
|
+
handleError(error) {
|
|
28
|
+
this.map?.logger.error(error, "Failed to export map image");
|
|
29
|
+
}
|
|
30
|
+
onClick = async () => {
|
|
31
|
+
if (!this.map || this.isExporting)
|
|
32
|
+
return;
|
|
33
|
+
this.isExporting = true;
|
|
34
|
+
this.render();
|
|
35
|
+
this.map
|
|
36
|
+
.export({
|
|
37
|
+
hideControls: true,
|
|
38
|
+
hideMarkers: false,
|
|
39
|
+
hidePopups: false,
|
|
40
|
+
...this.options,
|
|
41
|
+
})
|
|
42
|
+
.then((img) => this.downloadImage(img))
|
|
43
|
+
.catch((error) => this.handleError(error))
|
|
44
|
+
.finally(() => {
|
|
45
|
+
this.isExporting = false;
|
|
46
|
+
this.render();
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
render() {
|
|
50
|
+
if (!this.container) {
|
|
51
|
+
this.map?.logger.error("Export control container not found for rendering");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
render(h(Button, { isExporting: this.isExporting, onClick: this.onClick }), this.container);
|
|
55
|
+
}
|
|
56
|
+
unmount() {
|
|
57
|
+
if (!this.container) {
|
|
58
|
+
this.map?.logger.error("Export control container not found during unmount");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
render(null, this.container);
|
|
62
|
+
}
|
|
63
|
+
onAdd(map) {
|
|
64
|
+
this.map = map;
|
|
65
|
+
this.container = document.createElement("div");
|
|
66
|
+
this.container.className = "mapka-export-control";
|
|
67
|
+
this.render();
|
|
68
|
+
return this.container;
|
|
69
|
+
}
|
|
70
|
+
onRemove() {
|
|
71
|
+
this.unmount();
|
|
72
|
+
this.container?.remove?.();
|
|
73
|
+
this.container = undefined;
|
|
74
|
+
this.map = undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export * from "maplibre-gl";
|
|
|
2
2
|
export * from "./types/layer.js";
|
|
3
3
|
export * from "./types/marker.js";
|
|
4
4
|
export * from "./types/style.js";
|
|
5
|
+
export * from "./types/export.js";
|
|
5
6
|
export { MapkaMap as Map } from "./map.js";
|
|
6
7
|
export { MapkaMapOptions as MapOptions } from "./map.js";
|
|
8
|
+
export { MapkaExportControl, MapkaExportControlOptions, } from "./controls/MapkaExportControl.js";
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,eAAe,IAAI,UAAU,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,kCAAkC,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -2,4 +2,6 @@ export * from "maplibre-gl";
|
|
|
2
2
|
export * from "./types/layer.js";
|
|
3
3
|
export * from "./types/marker.js";
|
|
4
4
|
export * from "./types/style.js";
|
|
5
|
+
export * from "./types/export.js";
|
|
5
6
|
export { MapkaMap as Map } from "./map.js";
|
|
7
|
+
export { MapkaExportControl, } from "./controls/MapkaExportControl.js";
|
package/lib/map.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as maplibregl from "maplibre-gl";
|
|
2
2
|
import type { Marker, Popup, MapOptions, StyleSwapOptions, StyleOptions, StyleSpecification } from "maplibre-gl";
|
|
3
3
|
import type { MapkaMarkerOptions, MapkaPopupOptions } from "./types/marker.js";
|
|
4
|
+
import type { MapkaExportOptions } from "./types/export.js";
|
|
4
5
|
export interface MapkaMapOptions extends MapOptions {
|
|
5
6
|
maxPopups?: number;
|
|
6
7
|
apiKey: string;
|
|
@@ -17,8 +18,14 @@ export type MapMapkaMarker = {
|
|
|
17
18
|
options: MapkaMarkerOptions;
|
|
18
19
|
marker: Marker;
|
|
19
20
|
};
|
|
21
|
+
interface Logger {
|
|
22
|
+
log: (...args: unknown[]) => void;
|
|
23
|
+
warn: (...args: unknown[]) => void;
|
|
24
|
+
error: (...args: unknown[]) => void;
|
|
25
|
+
}
|
|
20
26
|
export declare class MapkaMap extends maplibregl.Map {
|
|
21
27
|
static env: string;
|
|
28
|
+
logger: Logger;
|
|
22
29
|
markers: MapMapkaMarker[];
|
|
23
30
|
maxPopups: number;
|
|
24
31
|
popups: MapMapkaPopup[];
|
|
@@ -27,9 +34,11 @@ export declare class MapkaMap extends maplibregl.Map {
|
|
|
27
34
|
addMarkers(markers: MapkaMarkerOptions[]): void;
|
|
28
35
|
updateMarkers(markers: MapkaMarkerOptions[]): void;
|
|
29
36
|
removeMarkers(): void;
|
|
30
|
-
openPopup(popup: MapkaPopupOptions
|
|
37
|
+
openPopup(popup: MapkaPopupOptions): string;
|
|
31
38
|
closePopup(id: string): void;
|
|
32
|
-
updatePopup(popup: MapkaPopupOptions
|
|
39
|
+
updatePopup(popup: MapkaPopupOptions): void;
|
|
33
40
|
removePopups(): void;
|
|
41
|
+
export(options?: MapkaExportOptions): Promise<HTMLImageElement>;
|
|
34
42
|
}
|
|
43
|
+
export {};
|
|
35
44
|
//# sourceMappingURL=map.d.ts.map
|
package/lib/map.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAiB1C,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EAGL,UAAU,EAEV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAiB1C,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EAGL,UAAU,EAEV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;CAChC;AA0BD,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,WAAW,CAAC;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,UAAU,MAAM;IACd,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAED,qBAAa,QAAS,SAAQ,UAAU,CAAC,GAAG;IAC1C,MAAM,CAAC,GAAG,EAAE,MAAM,CAAU;IAErB,MAAM,EAAE,MAAM,CAAW;IACzB,OAAO,EAAE,cAAc,EAAE,CAAM;IAE/B,SAAS,EAAE,MAAM,CAAK;IACtB,MAAM,EAAE,aAAa,EAAE,CAAM;gBAEjB,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAa,EAAE,GAAG,OAAO,EAAE,EAAE,eAAe;IAoBpF,QAAQ,CACb,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAClC,OAAO,GAAE,gBAAgB,GAAG,YAAiB;IAexC,UAAU,CAAC,OAAO,EAAE,kBAAkB,EAAE;IAIxC,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE;IAI3C,aAAa;IAIb,SAAS,CAAC,KAAK,EAAE,iBAAiB;IAIlC,UAAU,CAAC,EAAE,EAAE,MAAM;IAIrB,WAAW,CAAC,KAAK,EAAE,iBAAiB;IAIpC,YAAY;IAIN,MAAM,CAAC,OAAO,CAAC,EAAE,kBAAkB;CAGjD"}
|
package/lib/map.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as maplibregl from "maplibre-gl";
|
|
2
2
|
import { loadLayersIcons } from "./modules/icons.js";
|
|
3
|
-
import { closeOnMapClickPopups, closePopupsById,
|
|
3
|
+
import { closeOnMapClickPopups, closePopupsById, openPopup, removePopups, updatePopup, } from "./modules/popup.js";
|
|
4
4
|
import { addMarkers, addStyleDiffMarkers, addStyleMarkers, removeMarkers, updateMarkers, } from "./modules/markers.js";
|
|
5
|
+
import { exportMap } from "./modules/export.js";
|
|
5
6
|
const noopTransformRequest = (url) => {
|
|
6
7
|
return {
|
|
7
8
|
url,
|
|
@@ -23,6 +24,7 @@ const noopTransformStyle = (_, next) => {
|
|
|
23
24
|
};
|
|
24
25
|
export class MapkaMap extends maplibregl.Map {
|
|
25
26
|
static env = "prod";
|
|
27
|
+
logger = console;
|
|
26
28
|
markers = [];
|
|
27
29
|
maxPopups = 1;
|
|
28
30
|
popups = [];
|
|
@@ -62,16 +64,19 @@ export class MapkaMap extends maplibregl.Map {
|
|
|
62
64
|
removeMarkers() {
|
|
63
65
|
removeMarkers(this);
|
|
64
66
|
}
|
|
65
|
-
openPopup(popup
|
|
66
|
-
return openPopup(this, popup
|
|
67
|
+
openPopup(popup) {
|
|
68
|
+
return openPopup(this, popup);
|
|
67
69
|
}
|
|
68
70
|
closePopup(id) {
|
|
69
71
|
closePopupsById(this, id);
|
|
70
72
|
}
|
|
71
|
-
updatePopup(popup
|
|
72
|
-
return updatePopup(this, popup
|
|
73
|
+
updatePopup(popup) {
|
|
74
|
+
return updatePopup(this, popup);
|
|
73
75
|
}
|
|
74
76
|
removePopups() {
|
|
75
77
|
removePopups(this);
|
|
76
78
|
}
|
|
79
|
+
async export(options) {
|
|
80
|
+
return exportMap(this, options);
|
|
81
|
+
}
|
|
77
82
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/modules/export.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,wBAAsB,SAAS,CAC7B,GAAG,EAAE,QAAQ,EACb,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CA+C3B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { toPng } from "html-to-image";
|
|
2
|
+
export async function exportMap(map, options = {}) {
|
|
3
|
+
const { hideControls = false, hideMarkers = false, hidePopups = false, bbox } = options;
|
|
4
|
+
const container = map.getContainer();
|
|
5
|
+
const originalBounds = map.getBounds();
|
|
6
|
+
if (bbox) {
|
|
7
|
+
map.fitBounds(bbox, { padding: 20, animate: false });
|
|
8
|
+
}
|
|
9
|
+
return new Promise((resolve, reject) => {
|
|
10
|
+
map.once("render", () => {
|
|
11
|
+
toPng(container, {
|
|
12
|
+
skipFonts: navigator.userAgent.includes("Firefox"),
|
|
13
|
+
filter: (node) => {
|
|
14
|
+
if (node.classList) {
|
|
15
|
+
const isControlsVisibleOrNotControl = !hideControls || !node.classList.contains("maplibregl-control-container");
|
|
16
|
+
const isMarkersVisibleOrNotMarker = !hideMarkers || !node.classList.contains("maplibregl-marker");
|
|
17
|
+
const isPopupsVisibleOrNotPopup = !hidePopups || !node.classList.contains("maplibregl-popup");
|
|
18
|
+
return (isControlsVisibleOrNotControl &&
|
|
19
|
+
isMarkersVisibleOrNotMarker &&
|
|
20
|
+
isPopupsVisibleOrNotPopup);
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
.then((dataUrl) => {
|
|
26
|
+
const img = new Image();
|
|
27
|
+
img.src = dataUrl;
|
|
28
|
+
img.onload = () => resolve(img);
|
|
29
|
+
img.onerror = reject;
|
|
30
|
+
})
|
|
31
|
+
.catch(reject)
|
|
32
|
+
.finally(() => {
|
|
33
|
+
if (bbox) {
|
|
34
|
+
map.fitBounds(originalBounds, { animate: false });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
map.triggerRepaint();
|
|
39
|
+
});
|
|
40
|
+
}
|
package/lib/modules/popup.d.ts
CHANGED
|
@@ -6,9 +6,9 @@ export declare function getPopupId(popup: {
|
|
|
6
6
|
}): string;
|
|
7
7
|
export declare function getOnClose(map: MapkaMap, id: string): () => void;
|
|
8
8
|
export declare function enforceMaxPopups(map: MapkaMap): void;
|
|
9
|
-
export declare function openPopup(map: MapkaMap, options: MapkaPopupOptions
|
|
9
|
+
export declare function openPopup(map: MapkaMap, options: MapkaPopupOptions): string;
|
|
10
10
|
export declare function updatePopupBaseOptions(popup: Popup, options: MapkaPopupOptions, newOptions: Omit<MapkaPopupOptions, "content">): Popup;
|
|
11
|
-
export declare function updatePopup(map: MapkaMap, { content, ...newOptions }: MapkaPopupOptions
|
|
11
|
+
export declare function updatePopup(map: MapkaMap, { content, ...newOptions }: MapkaPopupOptions): void;
|
|
12
12
|
export declare function closeOnMapClickPopups(map: MapkaMap): void;
|
|
13
13
|
export declare function closePopupsById(map: MapkaMap, id: string): void;
|
|
14
14
|
export declare function removePopups(map: MapkaMap): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../src/modules/popup.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,UAEhD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,cAEnD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,QAM7C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../src/modules/popup.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,UAEhD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,cAEnD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,QAM7C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,iBAAiB,UAqDlE;AAID,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,SAY/C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,EAAE,iBAAiB,QA0BvF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,QAQlD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAMxD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,QAMzC"}
|
package/lib/modules/popup.js
CHANGED
|
@@ -18,8 +18,8 @@ export function enforceMaxPopups(map) {
|
|
|
18
18
|
popupToRemove?.container.remove();
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
export function openPopup(map, options
|
|
22
|
-
const { lngLat, content, closeButton, ...popupOptions } = options;
|
|
21
|
+
export function openPopup(map, options) {
|
|
22
|
+
const { lngLat, content, closeButton, id = getPopupId(options), ...popupOptions } = options;
|
|
23
23
|
if (content instanceof HTMLElement) {
|
|
24
24
|
const popup = new Popup({
|
|
25
25
|
...popupOptions,
|
|
@@ -65,7 +65,7 @@ export function openPopup(map, options, id) {
|
|
|
65
65
|
return openPopup(map, {
|
|
66
66
|
...options,
|
|
67
67
|
content: newContent,
|
|
68
|
-
}
|
|
68
|
+
});
|
|
69
69
|
}
|
|
70
70
|
throw new Error("Invalid popup content");
|
|
71
71
|
}
|
|
@@ -82,7 +82,8 @@ export function updatePopupBaseOptions(popup, options, newOptions) {
|
|
|
82
82
|
}
|
|
83
83
|
return popup;
|
|
84
84
|
}
|
|
85
|
-
export function updatePopup(map, { content, ...newOptions }
|
|
85
|
+
export function updatePopup(map, { content, ...newOptions }) {
|
|
86
|
+
const id = getPopupId(newOptions);
|
|
86
87
|
if (content instanceof HTMLElement) {
|
|
87
88
|
const mapkaPopups = map.popups.filter((popup) => popup.id === id);
|
|
88
89
|
for (const { popup, options } of mapkaPopups) {
|
|
@@ -105,7 +106,7 @@ export function updatePopup(map, { content, ...newOptions }, id) {
|
|
|
105
106
|
return updatePopup(map, {
|
|
106
107
|
...newOptions,
|
|
107
108
|
content: newContent,
|
|
108
|
-
}
|
|
109
|
+
});
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
export function closeOnMapClickPopups(map) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/types/export.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mapka/maplibre-gl-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Mapka JS SDK",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"license": "Apache-2.0",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"es-toolkit": "^1.43.0",
|
|
27
|
+
"html-to-image": "^1.11.13",
|
|
27
28
|
"maplibre-gl": "^5.15.0",
|
|
28
29
|
"preact": "^10.28.0"
|
|
29
30
|
},
|
|
@@ -34,5 +35,5 @@
|
|
|
34
35
|
"!**/__tests__/",
|
|
35
36
|
"!lib/buildInfo.json"
|
|
36
37
|
],
|
|
37
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "912eb7ca07c1c2ab1e9eaadab20e2c1786c0e967"
|
|
38
39
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** biome-ignore-all lint/correctness/noUnusedImports: <explanation> */
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
|
|
4
|
+
export const DownloadIcon = () => {
|
|
5
|
+
return (
|
|
6
|
+
<svg
|
|
7
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
+
width="24"
|
|
9
|
+
height="24"
|
|
10
|
+
viewBox="0 0 24 24"
|
|
11
|
+
fill="none"
|
|
12
|
+
stroke="currentColor"
|
|
13
|
+
stroke-width="2"
|
|
14
|
+
stroke-linecap="round"
|
|
15
|
+
stroke-linejoin="round"
|
|
16
|
+
aria-label="Download"
|
|
17
|
+
>
|
|
18
|
+
<title>Download</title>
|
|
19
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
20
|
+
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" />
|
|
21
|
+
<path d="M7 11l5 5l5 -5" />
|
|
22
|
+
<path d="M12 4l0 12" />
|
|
23
|
+
</svg>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** biome-ignore-all lint/correctness/noUnusedImports: <explanation> */
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
|
|
4
|
+
export const ProgressDownIcon = () => {
|
|
5
|
+
return (
|
|
6
|
+
<svg
|
|
7
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
+
width="24"
|
|
9
|
+
height="24"
|
|
10
|
+
viewBox="0 0 24 24"
|
|
11
|
+
fill="none"
|
|
12
|
+
stroke="currentColor"
|
|
13
|
+
stroke-width="2"
|
|
14
|
+
stroke-linecap="round"
|
|
15
|
+
stroke-linejoin="round"
|
|
16
|
+
class="icon icon-tabler icons-tabler-outline icon-tabler-progress-down"
|
|
17
|
+
>
|
|
18
|
+
<title>Progress Download</title>
|
|
19
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
20
|
+
<path d="M10 20.777a8.942 8.942 0 0 1 -2.48 -.969" />
|
|
21
|
+
<path d="M14 3.223a9.003 9.003 0 0 1 0 17.554" />
|
|
22
|
+
<path d="M4.579 17.093a8.961 8.961 0 0 1 -1.227 -2.592" />
|
|
23
|
+
<path d="M3.124 10.5c.16 -.95 .468 -1.85 .9 -2.675l.169 -.305" />
|
|
24
|
+
<path d="M6.907 4.579a8.954 8.954 0 0 1 3.093 -1.356" />
|
|
25
|
+
<path d="M12 9v6" />
|
|
26
|
+
<path d="M15 12l-3 3l-3 -3" />
|
|
27
|
+
</svg>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// biome-ignore lint/correctness/noUnusedImports: preact jsx
|
|
2
|
+
import { h } from "preact";
|
|
3
|
+
import { render } from "preact";
|
|
4
|
+
import { DownloadIcon } from "../components/DownloadIcon.js";
|
|
5
|
+
import { ProgressDownIcon } from "../components/ProgressDownIcon.js";
|
|
6
|
+
import type { IControl } from "maplibre-gl";
|
|
7
|
+
import type { MapkaMap } from "../map.js";
|
|
8
|
+
import type { MapkaExportOptions } from "../types/export.js";
|
|
9
|
+
|
|
10
|
+
export interface MapkaExportControlOptions extends MapkaExportOptions {
|
|
11
|
+
filename?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Button = ({ isExporting, onClick }: { isExporting: boolean; onClick: () => void }) => {
|
|
15
|
+
return (
|
|
16
|
+
<button
|
|
17
|
+
type="button"
|
|
18
|
+
className="maplibregl-ctrl maplibregl-ctrl-group"
|
|
19
|
+
title="Export map as PNG"
|
|
20
|
+
aria-label="Export map as PNG"
|
|
21
|
+
disabled={isExporting}
|
|
22
|
+
onClick={onClick}
|
|
23
|
+
>
|
|
24
|
+
{isExporting ? <ProgressDownIcon /> : <DownloadIcon />}
|
|
25
|
+
</button>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export class MapkaExportControl implements IControl {
|
|
30
|
+
private map: MapkaMap | undefined;
|
|
31
|
+
private container: HTMLDivElement | undefined;
|
|
32
|
+
private options: MapkaExportControlOptions;
|
|
33
|
+
private isExporting = false;
|
|
34
|
+
|
|
35
|
+
constructor(options: MapkaExportControlOptions = {}) {
|
|
36
|
+
this.options = {
|
|
37
|
+
filename: "map-export",
|
|
38
|
+
...options,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private downloadImage(img: HTMLImageElement): void {
|
|
43
|
+
const link = document.createElement("a");
|
|
44
|
+
link.download = `${this.options.filename}.png`;
|
|
45
|
+
link.href = img.src;
|
|
46
|
+
|
|
47
|
+
link.click();
|
|
48
|
+
link.remove();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private handleError(error: Error) {
|
|
52
|
+
this.map?.logger.error(error, "Failed to export map image");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private onClick = async (): Promise<void> => {
|
|
56
|
+
if (!this.map || this.isExporting) return;
|
|
57
|
+
|
|
58
|
+
this.isExporting = true;
|
|
59
|
+
this.render();
|
|
60
|
+
|
|
61
|
+
this.map
|
|
62
|
+
.export({
|
|
63
|
+
hideControls: true,
|
|
64
|
+
hideMarkers: false,
|
|
65
|
+
hidePopups: false,
|
|
66
|
+
...this.options,
|
|
67
|
+
})
|
|
68
|
+
.then((img) => this.downloadImage(img))
|
|
69
|
+
.catch((error) => this.handleError(error))
|
|
70
|
+
.finally(() => {
|
|
71
|
+
this.isExporting = false;
|
|
72
|
+
this.render();
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
private render(): void {
|
|
77
|
+
if (!this.container) {
|
|
78
|
+
this.map?.logger.error("Export control container not found for rendering");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
render(<Button isExporting={this.isExporting} onClick={this.onClick} />, this.container);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private unmount(): void {
|
|
85
|
+
if (!this.container) {
|
|
86
|
+
this.map?.logger.error("Export control container not found during unmount");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
render(null, this.container);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public onAdd(map: MapkaMap): HTMLElement {
|
|
93
|
+
this.map = map;
|
|
94
|
+
|
|
95
|
+
this.container = document.createElement("div");
|
|
96
|
+
this.container.className = "mapka-export-control";
|
|
97
|
+
|
|
98
|
+
this.render();
|
|
99
|
+
|
|
100
|
+
return this.container;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public onRemove(): void {
|
|
104
|
+
this.unmount();
|
|
105
|
+
|
|
106
|
+
this.container?.remove?.();
|
|
107
|
+
|
|
108
|
+
this.container = undefined;
|
|
109
|
+
this.map = undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,11 @@ export * from "maplibre-gl";
|
|
|
2
2
|
export * from "./types/layer.js";
|
|
3
3
|
export * from "./types/marker.js";
|
|
4
4
|
export * from "./types/style.js";
|
|
5
|
+
export * from "./types/export.js";
|
|
5
6
|
|
|
6
7
|
export { MapkaMap as Map } from "./map.js";
|
|
7
8
|
export { MapkaMapOptions as MapOptions } from "./map.js";
|
|
9
|
+
export {
|
|
10
|
+
MapkaExportControl,
|
|
11
|
+
MapkaExportControlOptions,
|
|
12
|
+
} from "./controls/MapkaExportControl.js";
|