@k2b/ui 0.35.0 → 0.36.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/dist/browser/content/MapView.js +128 -13
- package/dist/browser/content/MapView.js.map +1 -1
- package/dist/browser/content/MapViewFrame.js +1 -1
- package/dist/browser/content/MapViewFrame.js.map +1 -1
- package/dist/browser/content/index.js +1 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/map-view-glyphs.js +23 -0
- package/dist/browser/content/map-view-glyphs.js.map +1 -0
- package/dist/browser/content/map-view-live.js +45 -22
- package/dist/browser/content/map-view-live.js.map +1 -1
- package/dist/browser/content/map-view-snapshot.js +191 -0
- package/dist/browser/content/map-view-snapshot.js.map +1 -0
- package/dist/browser/content/map-view-types.js.map +1 -1
- package/dist/browser/inputs/Combobox.js +139 -62
- package/dist/browser/inputs/Combobox.js.map +1 -1
- package/dist/browser/inputs/TextInput.js +1 -1
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +73 -70
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/ScrollArea.js +4 -1
- package/dist/browser/layout/ScrollArea.js.map +1 -1
- package/dist/ssr/content/MapView.js +128 -13
- package/dist/ssr/content/MapView.js.map +1 -1
- package/dist/ssr/content/MapViewFrame.js +1 -1
- package/dist/ssr/content/MapViewFrame.js.map +1 -1
- package/dist/ssr/content/index.js +1 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/map-view-glyphs.js +23 -0
- package/dist/ssr/content/map-view-glyphs.js.map +1 -0
- package/dist/ssr/content/map-view-snapshot.js +191 -0
- package/dist/ssr/content/map-view-snapshot.js.map +1 -0
- package/dist/ssr/content/map-view-types.js.map +1 -1
- package/dist/ssr/inputs/Combobox.js +66 -20
- package/dist/ssr/inputs/Combobox.js.map +1 -1
- package/dist/ssr/inputs/TextInput.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +1 -1
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/ScrollArea.js +4 -1
- package/dist/ssr/layout/ScrollArea.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/content/MapViewFrame.d.ts +1 -1
- package/dist/types/content/index.d.ts +2 -1
- package/dist/types/content/map-view-glyphs.d.ts +5 -0
- package/dist/types/content/map-view-live.d.ts +1 -1
- package/dist/types/content/map-view-snapshot.d.ts +13 -0
- package/dist/types/content/map-view-types.d.ts +15 -0
- package/dist/types/inputs/Combobox.d.ts +12 -0
- package/dist/types/inputs/TextInput.d.ts +2 -1
- package/dist/types/layout/AppWorkspace.d.ts +4 -1
- package/dist/types/layout/ScrollArea.d.ts +2 -0
- package/package.json +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/map-view-glyphs.ts"],"sourcesContent":["import { PbfReader } from \"pbf\";\n\ntype Glyph = { id?: number; bitmap?: Uint8Array; width?: number; height?: number; left?: number; top?: number; advance?: number };\nconst readGlyph = (tag: number, glyph: Glyph, pbf: PbfReader) => {\n if (tag === 1) glyph.id = pbf.readVarint();\n else if (tag === 2) glyph.bitmap = pbf.readBytes();\n else if (tag === 3) glyph.width = pbf.readVarint();\n else if (tag === 4) glyph.height = pbf.readVarint();\n else if (tag === 5) glyph.left = pbf.readSVarint();\n else if (tag === 6) glyph.top = pbf.readSVarint();\n else if (tag === 7) glyph.advance = pbf.readVarint();\n};\n\n/**\n * Validate the glyphs MapLibre will decode before it can silently substitute local fonts.\n * Uses the same PBF reader and 3px bitmap border as MapLibre 6, without allocating glyph images.\n */\nexport function validateMapGlyphs(data: ArrayBuffer): void {\n let count = 0;\n new PbfReader(data).readFields((tag, _unused, pbf) => {\n if (tag !== 1) return;\n pbf.readMessage((tag, _unused, pbf) => {\n if (tag !== 3) return;\n const glyph = pbf.readMessage<Glyph>(readGlyph, {});\n if (\n glyph.id === undefined ||\n !Number.isInteger(glyph.id) ||\n glyph.id < 0 ||\n glyph.id > 0x10ffff ||\n glyph.width === undefined ||\n glyph.height === undefined ||\n glyph.left === undefined ||\n glyph.top === undefined ||\n glyph.advance === undefined ||\n (!glyph.bitmap && (glyph.width !== 0 || glyph.height !== 0)) ||\n (glyph.bitmap !== undefined && glyph.bitmap.byteLength !== (glyph.width + 6) * (glyph.height + 6))\n )\n throw new Error(\"Invalid map glyph data\");\n count++;\n }, null);\n }, null);\n if (!count) throw new Error(\"Missing map glyph data\");\n}\n"],"mappings":"AAAA,SAAS,SAAS,QAAQ,KAAK;AAG/B,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,KAAY,EAAE,GAAc,KAAK;EAC/D,IAAI,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KACtC,IAAI,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,KAC9C,IAAI,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAC9C,IAAI,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAC/C,IAAI,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAC9C,IAAI,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAC7C,IAAI,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;AACtD,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,SAAS,iBAAiB,CAAC,IAAiB,EAAQ;EACzD,IAAI,KAAK,GAAG,CAAC;EACb,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,KAAK;IACpD,IAAI,GAAG,KAAK,CAAC,EAAE;IACf,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,KAAK;MACrC,IAAI,GAAG,KAAK,CAAC,EAAE;MACf,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAQ,SAAS,EAAE,CAAC,CAAC,CAAC;MACnD,IACE,KAAK,CAAC,EAAE,KAAK,SAAS,IACtB,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,IAC3B,KAAK,CAAC,EAAE,GAAG,CAAC,IACZ,KAAK,CAAC,EAAE,GAAG,QAAQ,IACnB,KAAK,CAAC,KAAK,KAAK,SAAS,IACzB,KAAK,CAAC,MAAM,KAAK,SAAS,IAC1B,KAAK,CAAC,IAAI,KAAK,SAAS,IACxB,KAAK,CAAC,GAAG,KAAK,SAAS,IACvB,KAAK,CAAC,OAAO,KAAK,SAAS,IAC1B,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAE,IAC3D,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,UAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,EAElG,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC;MAC3C,KAAK,EAAE;IACT,CAAC,EAAE,IAAI,CAAC;EACV,CAAC,EAAE,IAAI,CAAC;EACR,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC;AACvD","ignoreList":[]}
|
|
@@ -2,40 +2,63 @@
|
|
|
2
2
|
import { addProtocol, LngLat, Map, removeProtocol, setWorkerUrl } from "maplibre-gl";
|
|
3
3
|
// The build points this at a copy named map-view-worker.js, because @k2b/ssr serves only .js files.
|
|
4
4
|
import workerUrl from "./map-view-worker.js" with { type: "file" };
|
|
5
|
-
|
|
5
|
+
import { validateMapGlyphs } from "./map-view-glyphs";
|
|
6
|
+
let resourceProtocolId = 0;
|
|
7
|
+
export function createMap(options, resourceFailed) {
|
|
6
8
|
setWorkerUrl(new URL(workerUrl, import.meta.url).href);
|
|
7
|
-
// MapLibre
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// MapLibre 6 substitutes local glyphs on failure and treats HTTP 404 tiles as empty.
|
|
10
|
+
// A map error listener cannot observe either failure. Use its public protocol hook to keep failure explicit,
|
|
11
|
+
// without a second request, global fetch patch, provider URL, or cross-map shared state.
|
|
12
|
+
const protocol = `k2b-map-resource-${++resourceProtocolId}`;
|
|
13
|
+
const lifetime = new AbortController();
|
|
14
|
+
addProtocol(protocol, async (request, cancellation) => {
|
|
15
|
+
const signal = AbortSignal.any([lifetime.signal, cancellation.signal]);
|
|
11
16
|
try {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
const path = request.url.slice(protocol.length + 3);
|
|
18
|
+
const separator = path.indexOf("/");
|
|
19
|
+
const glyph = path.slice(0, separator) === "Glyphs";
|
|
20
|
+
const response = await fetch(decodeURIComponent(path.slice(separator + 1)), {
|
|
21
|
+
method: request.method,
|
|
22
|
+
headers: request.headers,
|
|
23
|
+
body: request.body,
|
|
24
|
+
credentials: request.credentials ?? "same-origin",
|
|
25
|
+
cache: request.cache,
|
|
26
|
+
referrerPolicy: request.referrerPolicy,
|
|
27
|
+
signal
|
|
18
28
|
});
|
|
19
|
-
if (!response.ok)
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
void response.body?.cancel().catch(() => {});
|
|
31
|
+
throw new Error("Map resource failed");
|
|
32
|
+
}
|
|
33
|
+
const data = await response.arrayBuffer();
|
|
34
|
+
signal.throwIfAborted();
|
|
35
|
+
if (glyph) validateMapGlyphs(data);
|
|
20
36
|
return {
|
|
21
|
-
data
|
|
37
|
+
data,
|
|
38
|
+
cacheControl: response.headers.get("cache-control") ?? undefined,
|
|
39
|
+
expires: response.headers.get("expires") ?? undefined,
|
|
40
|
+
etag: response.headers.get("etag") ?? undefined
|
|
22
41
|
};
|
|
23
42
|
} catch {
|
|
24
|
-
if (!
|
|
25
|
-
throw new Error("Map
|
|
43
|
+
if (!signal.aborted) resourceFailed();
|
|
44
|
+
throw new Error("Map resource failed");
|
|
26
45
|
}
|
|
27
46
|
});
|
|
47
|
+
const clean = () => {
|
|
48
|
+
lifetime.abort();
|
|
49
|
+
removeProtocol(protocol);
|
|
50
|
+
};
|
|
28
51
|
let map;
|
|
29
52
|
try {
|
|
30
53
|
map = new Map({
|
|
31
54
|
...options,
|
|
32
|
-
async
|
|
55
|
+
transformRequest: async (url, type) => {
|
|
33
56
|
const request = (await options.transformRequest?.(url, type)) ?? {
|
|
34
57
|
url
|
|
35
58
|
};
|
|
36
|
-
return type === "Glyphs" ? {
|
|
59
|
+
return type === "Glyphs" || type === "Tile" ? {
|
|
37
60
|
...request,
|
|
38
|
-
url: `${protocol}
|
|
61
|
+
url: `${protocol}://${type}/${encodeURIComponent(new URL(request.url, location.href).href)}`
|
|
39
62
|
} : request;
|
|
40
63
|
},
|
|
41
64
|
// MapLibre would move a wide or polar fit to keep the poles out of view; the server frame cannot know that rule,
|
|
@@ -45,11 +68,11 @@ export function createMap(options, onResourceError) {
|
|
|
45
68
|
zoom: Math.max(options.minZoom ?? -2, Math.min(options.maxZoom ?? 22, zoom))
|
|
46
69
|
})
|
|
47
70
|
});
|
|
48
|
-
} catch (
|
|
49
|
-
|
|
50
|
-
throw
|
|
71
|
+
} catch (error) {
|
|
72
|
+
clean();
|
|
73
|
+
throw error;
|
|
51
74
|
}
|
|
52
|
-
map.on("remove",
|
|
75
|
+
map.on("remove", clean);
|
|
53
76
|
map.touchZoomRotate.disableRotation();
|
|
54
77
|
map.keyboard.disableRotation();
|
|
55
78
|
// The shared overlay projects a flat, north-up Mercator plane even if a style requests a globe.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/map-view-live.ts"],"sourcesContent":["/// <reference path=\"./maplibre-worker.d.ts\" />\nimport { addProtocol, LngLat, Map, type MapOptions, removeProtocol, setWorkerUrl } from \"maplibre-gl\";\n// The build points this at a copy named map-view-worker.js, because @k2b/ssr serves only .js files.\nimport workerUrl from \"maplibre-gl/dist/maplibre-gl-worker.mjs\" with { type: \"file\" };\n\nexport function createMap(options: MapOptions,
|
|
1
|
+
{"version":3,"names":[],"sources":["content/map-view-live.ts"],"sourcesContent":["/// <reference path=\"./maplibre-worker.d.ts\" />\nimport { addProtocol, LngLat, Map, type MapOptions, removeProtocol, setWorkerUrl } from \"maplibre-gl\";\n// The build points this at a copy named map-view-worker.js, because @k2b/ssr serves only .js files.\nimport workerUrl from \"maplibre-gl/dist/maplibre-gl-worker.mjs\" with { type: \"file\" };\n\nimport { validateMapGlyphs } from \"./map-view-glyphs\";\n\nlet resourceProtocolId = 0;\n\nexport function createMap(options: MapOptions, resourceFailed: () => void): Map {\n setWorkerUrl(new URL(workerUrl, import.meta.url).href);\n // MapLibre 6 substitutes local glyphs on failure and treats HTTP 404 tiles as empty.\n // A map error listener cannot observe either failure. Use its public protocol hook to keep failure explicit,\n // without a second request, global fetch patch, provider URL, or cross-map shared state.\n const protocol = `k2b-map-resource-${++resourceProtocolId}`;\n const lifetime = new AbortController();\n addProtocol(protocol, async (request, cancellation) => {\n const signal = AbortSignal.any([lifetime.signal, cancellation.signal]);\n try {\n const path = request.url.slice(protocol.length + 3);\n const separator = path.indexOf(\"/\");\n const glyph = path.slice(0, separator) === \"Glyphs\";\n const response = await fetch(decodeURIComponent(path.slice(separator + 1)), {\n method: request.method,\n headers: request.headers,\n body: request.body,\n credentials: request.credentials ?? \"same-origin\",\n cache: request.cache,\n referrerPolicy: request.referrerPolicy,\n signal,\n });\n if (!response.ok) {\n void response.body?.cancel().catch(() => {});\n throw new Error(\"Map resource failed\");\n }\n const data = await response.arrayBuffer();\n signal.throwIfAborted();\n if (glyph) validateMapGlyphs(data);\n return {\n data,\n cacheControl: response.headers.get(\"cache-control\") ?? undefined,\n expires: response.headers.get(\"expires\") ?? undefined,\n etag: response.headers.get(\"etag\") ?? undefined,\n };\n } catch {\n if (!signal.aborted) resourceFailed();\n throw new Error(\"Map resource failed\");\n }\n });\n const clean = () => {\n lifetime.abort();\n removeProtocol(protocol);\n };\n let map: Map;\n try {\n map = new Map({\n ...options,\n transformRequest: async (url, type) => {\n const request = (await options.transformRequest?.(url, type)) ?? { url };\n return type === \"Glyphs\" || type === \"Tile\"\n ? { ...request, url: `${protocol}://${type}/${encodeURIComponent(new URL(request.url, location.href).href)}` }\n : request;\n },\n // MapLibre would move a wide or polar fit to keep the poles out of view; the server frame cannot know that rule,\n // so the camera stays where fitCamera puts it and only latitude and zoom keep their ordinary limits.\n transformConstrain: (center, zoom) => ({\n center: new LngLat(center.lng, Math.max(-85.051129, Math.min(85.051129, center.lat))),\n zoom: Math.max(options.minZoom ?? -2, Math.min(options.maxZoom ?? 22, zoom)),\n }),\n });\n } catch (error) {\n clean();\n throw error;\n }\n map.on(\"remove\", clean);\n map.touchZoomRotate.disableRotation();\n map.keyboard.disableRotation();\n // The shared overlay projects a flat, north-up Mercator plane even if a style requests a globe.\n // Terrain would lift features off that plane, so a style's terrain is switched off as well.\n map.on(\"style.load\", () => {\n map.setProjection({ type: \"mercator\" });\n if (map.getTerrain()) map.setTerrain(null);\n });\n return map;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/** Same decoded RGBA budget as Cloud's isolated print-image worker (64 MiB). */
|
|
2
|
+
export const MAP_SNAPSHOT_MAX_PIXELS = 16 * 1024 * 1024;
|
|
3
|
+
export class MapSnapshotError extends Error {
|
|
4
|
+
constructor(code) {
|
|
5
|
+
super(`Map snapshot: ${code}`);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.name = "MapSnapshotError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function snapshotAborted(signal) {
|
|
11
|
+
return signal.reason instanceof MapSnapshotError ? signal.reason : new MapSnapshotError("aborted");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Also observes late rejection; a cancelled image/font/encoding operation never becomes unhandled. */
|
|
15
|
+
export function snapshotWait(promise, signal) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const abort = () => reject(snapshotAborted(signal));
|
|
18
|
+
if (signal.aborted) return abort();
|
|
19
|
+
signal.addEventListener("abort", abort, {
|
|
20
|
+
once: true
|
|
21
|
+
});
|
|
22
|
+
promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const svgNamespace = "http://www.w3.org/2000/svg";
|
|
26
|
+
// Only renderer-owned shapes and paint cross into the rasterizer; no foreignObject, links, images or CSS URLs.
|
|
27
|
+
const paints = ["fill", "fill-opacity", "stroke", "stroke-width", "stroke-opacity", "stroke-dasharray", "stroke-linecap", "stroke-linejoin"];
|
|
28
|
+
function geometryImage(root, bounds) {
|
|
29
|
+
const source = root.querySelector(".k2b-map-view__geometry");
|
|
30
|
+
if (!source) return;
|
|
31
|
+
const svg = document.createElementNS(svgNamespace, "svg");
|
|
32
|
+
svg.setAttribute("width", String(bounds.width));
|
|
33
|
+
svg.setAttribute("height", String(bounds.height));
|
|
34
|
+
const geometry = document.createElementNS(svgNamespace, "svg");
|
|
35
|
+
const box = source.getBoundingClientRect();
|
|
36
|
+
for (const [name, value] of Object.entries({
|
|
37
|
+
x: box.left - bounds.left,
|
|
38
|
+
y: box.top - bounds.top,
|
|
39
|
+
width: box.width,
|
|
40
|
+
height: box.height,
|
|
41
|
+
viewBox: source.getAttribute("viewBox") ?? "",
|
|
42
|
+
preserveAspectRatio: "none",
|
|
43
|
+
overflow: "visible"
|
|
44
|
+
})) geometry.setAttribute(name, String(value));
|
|
45
|
+
for (const shape of source.querySelectorAll("path")) {
|
|
46
|
+
const copy = document.createElementNS(svgNamespace, shape.localName);
|
|
47
|
+
for (const name of ["d", "cx", "cy", "r", "vector-effect"]) {
|
|
48
|
+
const value = shape.getAttribute(name);
|
|
49
|
+
if (value !== null) copy.setAttribute(name, value);
|
|
50
|
+
}
|
|
51
|
+
const style = getComputedStyle(shape);
|
|
52
|
+
for (const name of paints) {
|
|
53
|
+
const value = style.getPropertyValue(name);
|
|
54
|
+
if (value.includes("url(")) throw new MapSnapshotError("capture_failed");
|
|
55
|
+
copy.setAttribute(name, value);
|
|
56
|
+
}
|
|
57
|
+
geometry.append(copy);
|
|
58
|
+
}
|
|
59
|
+
svg.append(geometry);
|
|
60
|
+
const image = new Image();
|
|
61
|
+
image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;
|
|
62
|
+
return image;
|
|
63
|
+
}
|
|
64
|
+
function drawPins(ctx, root, bounds) {
|
|
65
|
+
const pins = Array.from(root.querySelectorAll(".k2b-map-view__pin"));
|
|
66
|
+
// The selected pin paints above the others, as in the DOM.
|
|
67
|
+
pins.sort((a, b) => Number(a.getAttribute("aria-pressed") === "true") - Number(b.getAttribute("aria-pressed") === "true"));
|
|
68
|
+
for (const pin of pins) {
|
|
69
|
+
const box = pin.getBoundingClientRect();
|
|
70
|
+
const style = getComputedStyle(pin);
|
|
71
|
+
const x = box.left - bounds.left,
|
|
72
|
+
y = box.top - bounds.top;
|
|
73
|
+
// Resolve CSS variables through a paint property, since custom properties can still contain var().
|
|
74
|
+
const selected = pin.getAttribute("aria-pressed") === "true" || pin.hasAttribute("data-selected");
|
|
75
|
+
const stop = pin.hasAttribute("data-stop");
|
|
76
|
+
const surface = getComputedStyle(root.querySelector(".k2b-map-view__attribution") ?? root).backgroundColor;
|
|
77
|
+
ctx.save();
|
|
78
|
+
if (pin.hasAttribute("data-drop")) {
|
|
79
|
+
const span = pin.querySelector("span");
|
|
80
|
+
ctx.fillStyle = getComputedStyle(span).backgroundColor;
|
|
81
|
+
ctx.beginPath();
|
|
82
|
+
ctx.ellipse(x + box.width / 2, y + box.height / 2, box.width / 2, box.height / 2, 0, Math.PI, Math.PI * 2);
|
|
83
|
+
ctx.lineTo(x + box.width, y + box.height * 0.68);
|
|
84
|
+
ctx.lineTo(x + box.width / 2, y + box.height);
|
|
85
|
+
ctx.lineTo(x, y + box.height * 0.68);
|
|
86
|
+
ctx.closePath();
|
|
87
|
+
ctx.fill();
|
|
88
|
+
if (selected) {
|
|
89
|
+
ctx.fillStyle = surface;
|
|
90
|
+
ctx.beginPath();
|
|
91
|
+
ctx.arc(x + box.width / 2, y + box.height * 0.34, 4, 0, Math.PI * 2);
|
|
92
|
+
ctx.fill();
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
ctx.beginPath();
|
|
96
|
+
ctx.arc(x + box.width / 2, y + box.height / 2, box.width / 2 + 2.5, 0, Math.PI * 2);
|
|
97
|
+
ctx.fillStyle = surface;
|
|
98
|
+
ctx.fill();
|
|
99
|
+
ctx.beginPath();
|
|
100
|
+
ctx.arc(x + box.width / 2, y + box.height / 2, box.width / 2, 0, Math.PI * 2);
|
|
101
|
+
ctx.fillStyle = style.backgroundColor;
|
|
102
|
+
ctx.fill();
|
|
103
|
+
// The first box-shadow is the resolved inset tone ring. Text ink can differ in dark mode.
|
|
104
|
+
const ring = style.boxShadow.match(/(?:rgba?|color|oklch|oklab)\([^)]*\)/)?.[0];
|
|
105
|
+
if (!ring && !stop && !selected) throw new MapSnapshotError("capture_failed");
|
|
106
|
+
ctx.strokeStyle = stop || selected ? style.backgroundColor : ring;
|
|
107
|
+
ctx.lineWidth = 2;
|
|
108
|
+
ctx.beginPath();
|
|
109
|
+
ctx.arc(x + box.width / 2, y + box.height / 2, box.width / 2 - 1, 0, Math.PI * 2);
|
|
110
|
+
ctx.stroke();
|
|
111
|
+
ctx.fillStyle = style.color;
|
|
112
|
+
ctx.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;
|
|
113
|
+
ctx.textAlign = "center";
|
|
114
|
+
ctx.textBaseline = "middle";
|
|
115
|
+
ctx.fillText(pin.textContent ?? "", x + box.width / 2, y + box.height / 2);
|
|
116
|
+
}
|
|
117
|
+
ctx.restore();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function drawAttribution(ctx, root, bounds) {
|
|
121
|
+
const attribution = root.querySelector(".k2b-map-view__attribution");
|
|
122
|
+
if (!attribution?.textContent?.trim()) throw new MapSnapshotError("capture_failed");
|
|
123
|
+
const box = attribution.getBoundingClientRect();
|
|
124
|
+
const style = getComputedStyle(attribution);
|
|
125
|
+
ctx.fillStyle = style.backgroundColor;
|
|
126
|
+
ctx.fillRect(box.left - bounds.left, box.top - bounds.top, box.width, box.height);
|
|
127
|
+
const walker = document.createTreeWalker(attribution, NodeFilter.SHOW_TEXT);
|
|
128
|
+
while (walker.nextNode()) {
|
|
129
|
+
const node = walker.currentNode;
|
|
130
|
+
const parent = node.parentElement;
|
|
131
|
+
const ink = getComputedStyle(parent);
|
|
132
|
+
ctx.fillStyle = ink.color;
|
|
133
|
+
ctx.font = `${ink.fontWeight} ${ink.fontSize} ${ink.fontFamily}`;
|
|
134
|
+
ctx.textBaseline = "top";
|
|
135
|
+
ctx.textAlign = "left";
|
|
136
|
+
// Per-character ranges preserve line breaks, wrapping, and bidi positions without capturing arbitrary HTML.
|
|
137
|
+
const range = document.createRange();
|
|
138
|
+
for (let i = 0; i < (node.textContent?.length ?? 0); i++) {
|
|
139
|
+
range.setStart(node, i);
|
|
140
|
+
range.setEnd(node, i + 1);
|
|
141
|
+
const r = range.getBoundingClientRect();
|
|
142
|
+
ctx.fillText(node.textContent[i], r.left - bounds.left, r.top - bounds.top);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Called synchronously in MapLibre's render event, before WebGL clears its drawing buffer. */
|
|
148
|
+
export async function rasterizeMapView(root, base, signal) {
|
|
149
|
+
const bounds = root.getBoundingClientRect();
|
|
150
|
+
const width = Math.round(bounds.width),
|
|
151
|
+
height = Math.round(bounds.height);
|
|
152
|
+
if (width < 1 || height < 1 || width > 16383 || height > 16383 || width * height > MAP_SNAPSHOT_MAX_PIXELS) throw new MapSnapshotError("too_large");
|
|
153
|
+
const canvas = document.createElement("canvas");
|
|
154
|
+
canvas.width = width;
|
|
155
|
+
canvas.height = height;
|
|
156
|
+
const ctx = canvas.getContext("2d");
|
|
157
|
+
if (!ctx) throw new MapSnapshotError("capture_failed");
|
|
158
|
+
try {
|
|
159
|
+
// Copy the GPU frame immediately. No preserveDrawingBuffer overhead for ordinary interactive maps.
|
|
160
|
+
ctx.drawImage(base, 0, 0, width, height);
|
|
161
|
+
const geometry = geometryImage(root, bounds);
|
|
162
|
+
// Save all overlay pixels before yielding, so subsequent DOM changes cannot mix revisions.
|
|
163
|
+
const overlay = document.createElement("canvas");
|
|
164
|
+
overlay.width = width;
|
|
165
|
+
overlay.height = height;
|
|
166
|
+
try {
|
|
167
|
+
const ink = overlay.getContext("2d");
|
|
168
|
+
drawPins(ink, root, bounds);
|
|
169
|
+
drawAttribution(ink, root, bounds);
|
|
170
|
+
if (geometry) {
|
|
171
|
+
await snapshotWait(geometry.decode(), signal);
|
|
172
|
+
ctx.drawImage(geometry, 0, 0, width, height);
|
|
173
|
+
}
|
|
174
|
+
ctx.drawImage(overlay, 0, 0);
|
|
175
|
+
} finally {
|
|
176
|
+
overlay.width = overlay.height = 0;
|
|
177
|
+
}
|
|
178
|
+
const data = await snapshotWait(new Promise((resolve, reject) => canvas.toBlob(blob => blob ? resolve(blob) : reject(new MapSnapshotError("capture_failed")), "image/png")), signal);
|
|
179
|
+
return {
|
|
180
|
+
data,
|
|
181
|
+
width,
|
|
182
|
+
height
|
|
183
|
+
};
|
|
184
|
+
} catch (error) {
|
|
185
|
+
if (error instanceof MapSnapshotError) throw error;
|
|
186
|
+
throw new MapSnapshotError("capture_failed");
|
|
187
|
+
} finally {
|
|
188
|
+
canvas.width = canvas.height = 0;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=map-view-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/map-view-snapshot.ts"],"sourcesContent":["import type { MapViewSnapshot } from \"./map-view-types\";\n\n/** Same decoded RGBA budget as Cloud's isolated print-image worker (64 MiB). */\nexport const MAP_SNAPSHOT_MAX_PIXELS = 16 * 1024 * 1024;\nexport type MapSnapshotErrorCode =\n | \"not_ready\"\n | \"resource_failed\"\n | \"changed\"\n | \"disposed\"\n | \"busy\"\n | \"too_large\"\n | \"timed_out\"\n | \"aborted\"\n | \"capture_failed\";\nexport class MapSnapshotError extends Error {\n constructor(readonly code: MapSnapshotErrorCode) {\n super(`Map snapshot: ${code}`);\n this.name = \"MapSnapshotError\";\n }\n}\n\nexport function snapshotAborted(signal: AbortSignal): MapSnapshotError {\n return signal.reason instanceof MapSnapshotError ? signal.reason : new MapSnapshotError(\"aborted\");\n}\n\n/** Also observes late rejection; a cancelled image/font/encoding operation never becomes unhandled. */\nexport function snapshotWait<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n return new Promise((resolve, reject) => {\n const abort = () => reject(snapshotAborted(signal));\n if (signal.aborted) return abort();\n signal.addEventListener(\"abort\", abort, { once: true });\n promise.then(resolve, reject).finally(() => signal.removeEventListener(\"abort\", abort));\n });\n}\n\nconst svgNamespace = \"http://www.w3.org/2000/svg\";\n// Only renderer-owned shapes and paint cross into the rasterizer; no foreignObject, links, images or CSS URLs.\nconst paints = [\n \"fill\",\n \"fill-opacity\",\n \"stroke\",\n \"stroke-width\",\n \"stroke-opacity\",\n \"stroke-dasharray\",\n \"stroke-linecap\",\n \"stroke-linejoin\",\n] as const;\nfunction geometryImage(root: HTMLElement, bounds: DOMRect): HTMLImageElement | undefined {\n const source = root.querySelector<SVGSVGElement>(\".k2b-map-view__geometry\");\n if (!source) return;\n const svg = document.createElementNS(svgNamespace, \"svg\");\n svg.setAttribute(\"width\", String(bounds.width));\n svg.setAttribute(\"height\", String(bounds.height));\n const geometry = document.createElementNS(svgNamespace, \"svg\");\n const box = source.getBoundingClientRect();\n for (const [name, value] of Object.entries({\n x: box.left - bounds.left,\n y: box.top - bounds.top,\n width: box.width,\n height: box.height,\n viewBox: source.getAttribute(\"viewBox\") ?? \"\",\n preserveAspectRatio: \"none\",\n overflow: \"visible\",\n }))\n geometry.setAttribute(name, String(value));\n for (const shape of source.querySelectorAll(\"path\")) {\n const copy = document.createElementNS(svgNamespace, shape.localName);\n for (const name of [\"d\", \"cx\", \"cy\", \"r\", \"vector-effect\"]) {\n const value = shape.getAttribute(name);\n if (value !== null) copy.setAttribute(name, value);\n }\n const style = getComputedStyle(shape);\n for (const name of paints) {\n const value = style.getPropertyValue(name);\n if (value.includes(\"url(\")) throw new MapSnapshotError(\"capture_failed\");\n copy.setAttribute(name, value);\n }\n geometry.append(copy);\n }\n svg.append(geometry);\n const image = new Image();\n image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;\n return image;\n}\n\nfunction drawPins(ctx: CanvasRenderingContext2D, root: HTMLElement, bounds: DOMRect) {\n const pins = Array.from(root.querySelectorAll<HTMLElement>(\".k2b-map-view__pin\"));\n // The selected pin paints above the others, as in the DOM.\n pins.sort((a, b) => Number(a.getAttribute(\"aria-pressed\") === \"true\") - Number(b.getAttribute(\"aria-pressed\") === \"true\"));\n for (const pin of pins) {\n const box = pin.getBoundingClientRect();\n const style = getComputedStyle(pin);\n const x = box.left - bounds.left,\n y = box.top - bounds.top;\n // Resolve CSS variables through a paint property, since custom properties can still contain var().\n const selected = pin.getAttribute(\"aria-pressed\") === \"true\" || pin.hasAttribute(\"data-selected\");\n const stop = pin.hasAttribute(\"data-stop\");\n const surface = getComputedStyle(root.querySelector(\".k2b-map-view__attribution\") ?? root).backgroundColor;\n ctx.save();\n if (pin.hasAttribute(\"data-drop\")) {\n const span = pin.querySelector(\"span\")!;\n ctx.fillStyle = getComputedStyle(span).backgroundColor;\n ctx.beginPath();\n ctx.ellipse(x + box.width / 2, y + box.height / 2, box.width / 2, box.height / 2, 0, Math.PI, Math.PI * 2);\n ctx.lineTo(x + box.width, y + box.height * 0.68);\n ctx.lineTo(x + box.width / 2, y + box.height);\n ctx.lineTo(x, y + box.height * 0.68);\n ctx.closePath();\n ctx.fill();\n if (selected) {\n ctx.fillStyle = surface;\n ctx.beginPath();\n ctx.arc(x + box.width / 2, y + box.height * 0.34, 4, 0, Math.PI * 2);\n ctx.fill();\n }\n } else {\n ctx.beginPath();\n ctx.arc(x + box.width / 2, y + box.height / 2, box.width / 2 + 2.5, 0, Math.PI * 2);\n ctx.fillStyle = surface;\n ctx.fill();\n ctx.beginPath();\n ctx.arc(x + box.width / 2, y + box.height / 2, box.width / 2, 0, Math.PI * 2);\n ctx.fillStyle = style.backgroundColor;\n ctx.fill();\n // The first box-shadow is the resolved inset tone ring. Text ink can differ in dark mode.\n const ring = style.boxShadow.match(/(?:rgba?|color|oklch|oklab)\\([^)]*\\)/)?.[0];\n if (!ring && !stop && !selected) throw new MapSnapshotError(\"capture_failed\");\n ctx.strokeStyle = stop || selected ? style.backgroundColor : ring!;\n ctx.lineWidth = 2;\n ctx.beginPath();\n ctx.arc(x + box.width / 2, y + box.height / 2, box.width / 2 - 1, 0, Math.PI * 2);\n ctx.stroke();\n ctx.fillStyle = style.color;\n ctx.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n ctx.fillText(pin.textContent ?? \"\", x + box.width / 2, y + box.height / 2);\n }\n ctx.restore();\n }\n}\n\nfunction drawAttribution(ctx: CanvasRenderingContext2D, root: HTMLElement, bounds: DOMRect) {\n const attribution = root.querySelector<HTMLElement>(\".k2b-map-view__attribution\");\n if (!attribution?.textContent?.trim()) throw new MapSnapshotError(\"capture_failed\");\n const box = attribution.getBoundingClientRect();\n const style = getComputedStyle(attribution);\n ctx.fillStyle = style.backgroundColor;\n ctx.fillRect(box.left - bounds.left, box.top - bounds.top, box.width, box.height);\n const walker = document.createTreeWalker(attribution, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n const parent = node.parentElement!;\n const ink = getComputedStyle(parent);\n ctx.fillStyle = ink.color;\n ctx.font = `${ink.fontWeight} ${ink.fontSize} ${ink.fontFamily}`;\n ctx.textBaseline = \"top\";\n ctx.textAlign = \"left\";\n // Per-character ranges preserve line breaks, wrapping, and bidi positions without capturing arbitrary HTML.\n const range = document.createRange();\n for (let i = 0; i < (node.textContent?.length ?? 0); i++) {\n range.setStart(node, i);\n range.setEnd(node, i + 1);\n const r = range.getBoundingClientRect();\n ctx.fillText(node.textContent![i]!, r.left - bounds.left, r.top - bounds.top);\n }\n }\n}\n\n/** Called synchronously in MapLibre's render event, before WebGL clears its drawing buffer. */\nexport async function rasterizeMapView(root: HTMLElement, base: HTMLCanvasElement, signal: AbortSignal): Promise<MapViewSnapshot> {\n const bounds = root.getBoundingClientRect();\n const width = Math.round(bounds.width),\n height = Math.round(bounds.height);\n if (width < 1 || height < 1 || width > 16383 || height > 16383 || width * height > MAP_SNAPSHOT_MAX_PIXELS)\n throw new MapSnapshotError(\"too_large\");\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new MapSnapshotError(\"capture_failed\");\n try {\n // Copy the GPU frame immediately. No preserveDrawingBuffer overhead for ordinary interactive maps.\n ctx.drawImage(base, 0, 0, width, height);\n const geometry = geometryImage(root, bounds);\n // Save all overlay pixels before yielding, so subsequent DOM changes cannot mix revisions.\n const overlay = document.createElement(\"canvas\");\n overlay.width = width;\n overlay.height = height;\n try {\n const ink = overlay.getContext(\"2d\")!;\n drawPins(ink, root, bounds);\n drawAttribution(ink, root, bounds);\n if (geometry) {\n await snapshotWait(geometry.decode(), signal);\n ctx.drawImage(geometry, 0, 0, width, height);\n }\n ctx.drawImage(overlay, 0, 0);\n } finally {\n overlay.width = overlay.height = 0;\n }\n const data = await snapshotWait(\n new Promise<Blob>((resolve, reject) =>\n canvas.toBlob((blob) => (blob ? resolve(blob) : reject(new MapSnapshotError(\"capture_failed\"))), \"image/png\"),\n ),\n signal,\n );\n return { data, width, height };\n } catch (error) {\n if (error instanceof MapSnapshotError) throw error;\n throw new MapSnapshotError(\"capture_failed\");\n } finally {\n canvas.width = canvas.height = 0;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/map-view-types.ts"],"sourcesContent":["import type { StyleSpecification } from \"maplibre-gl\";\nimport type { JSX } from \"solid-js\";\n\nexport type MapViewPoint = { lat: number; lon: number };\nexport type MapViewTone = \"accent\" | \"second\" | \"neutral\" | \"warning\";\nexport type MapViewMarker = {\n id: string;\n point: MapViewPoint;\n /** A number, a single letter, or \"+\". Omit for a drop pin. */\n mark?: number | string;\n label: string;\n tone?: MapViewTone;\n selected?: boolean;\n};\nexport type MapViewLineTone = \"accent\" | \"muted\" | \"preview\" | \"previous\";\nexport type MapViewLine = { id: string; tone?: MapViewLineTone } & ({ polyline6: string } | { points: MapViewPoint[] });\nexport type MapViewArea = { id: string; polygon: MapViewPoint[]; tone?: MapViewTone };\nexport type MapViewOwnLocation = { point: MapViewPoint; accuracyMeters?: number };\nexport type MapViewStyle = string | StyleSpecification;\nexport type MapViewStyleSource = MapViewStyle | { light: MapViewStyle; dark: MapViewStyle };\nexport type MapViewFit = \"all\" | \"markers\";\nexport type MapViewFrameProps = {\n markers?: MapViewMarker[];\n lines?: MapViewLine[];\n areas?: MapViewArea[];\n ownLocation?: MapViewOwnLocation;\n height: number;\n padding?: number;\n fit?: MapViewFit;\n selectedId?: string;\n attribution?: JSX.Element;\n class?: string;\n};\nexport type MapViewProps = Omit<MapViewFrameProps, \"attribution\"> & {\n style: MapViewStyleSource;\n attribution: JSX.Element;\n onSelect?: (id: string) => void;\n infoTile?: (marker: MapViewMarker) => JSX.Element;\n notice?: JSX.Element;\n empty?: JSX.Element;\n onLocate?: () => void;\n /** Observe rendering and resource failures without receiving provider responses or URLs. */\n onStateChange?: (state: \"static\" | \"loading\" | \"ready\" | \"error\" | \"no-webgl\" | \"empty\") => void;\n};\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["content/map-view-types.ts"],"sourcesContent":["import type { StyleSpecification } from \"maplibre-gl\";\nimport type { JSX } from \"solid-js\";\n\nexport type MapViewPoint = { lat: number; lon: number };\nexport type MapViewTone = \"accent\" | \"second\" | \"neutral\" | \"warning\";\nexport type MapViewMarker = {\n id: string;\n point: MapViewPoint;\n /** A number, a single letter, or \"+\". Omit for a drop pin. */\n mark?: number | string;\n label: string;\n tone?: MapViewTone;\n selected?: boolean;\n};\nexport type MapViewLineTone = \"accent\" | \"muted\" | \"preview\" | \"previous\";\nexport type MapViewLine = { id: string; tone?: MapViewLineTone } & ({ polyline6: string } | { points: MapViewPoint[] });\nexport type MapViewArea = { id: string; polygon: MapViewPoint[]; tone?: MapViewTone };\nexport type MapViewOwnLocation = { point: MapViewPoint; accuracyMeters?: number };\nexport type MapViewStyle = string | StyleSpecification;\nexport type MapViewStyleSource = MapViewStyle | { light: MapViewStyle; dark: MapViewStyle };\nexport type MapViewFit = \"all\" | \"markers\";\nexport type MapViewFrameProps = {\n markers?: MapViewMarker[];\n lines?: MapViewLine[];\n areas?: MapViewArea[];\n ownLocation?: MapViewOwnLocation;\n height: number;\n padding?: number;\n fit?: MapViewFit;\n selectedId?: string;\n attribution?: JSX.Element;\n class?: string;\n};\nexport type MapViewSnapshot = { data: Blob; width: number; height: number };\nexport type MapViewSnapshotOptions = { signal?: AbortSignal; timeoutMs?: number };\nexport type MapViewHandle = {\n /** Capture the current complete view; never loads, pans, refits, or retries provider resources. */\n snapshot: (options?: MapViewSnapshotOptions) => Promise<MapViewSnapshot>;\n};\nexport type MapViewProps = Omit<MapViewFrameProps, \"attribution\"> & {\n style: MapViewStyleSource;\n /** Browser-only handle; remains safely callable after disposal (rejects disposed). */\n ref?: (handle: MapViewHandle) => void;\n attribution: JSX.Element;\n onSelect?: (id: string) => void;\n infoTile?: (marker: MapViewMarker) => JSX.Element;\n notice?: JSX.Element;\n empty?: JSX.Element;\n onLocate?: () => void;\n /** Observe rendering and resource failures without receiving provider responses or URLs. */\n onStateChange?: (state: \"static\" | \"loading\" | \"ready\" | \"error\" | \"no-webgl\" | \"empty\") => void;\n};\n"],"mappings":"","ignoreList":[]}
|