@k2b/ui 0.30.0 → 0.31.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/browser/actions/Toolbar.js +2 -0
- package/dist/browser/actions/Toolbar.js.map +1 -1
- package/dist/browser/chat/ChatDecision.js +28 -2
- package/dist/browser/chat/ChatDecision.js.map +1 -1
- package/dist/browser/content/MapAttribution.js +27 -0
- package/dist/browser/content/MapAttribution.js.map +1 -0
- package/dist/browser/content/MapView.js +553 -0
- package/dist/browser/content/MapView.js.map +1 -0
- package/dist/browser/content/MapViewFrame.js +395 -0
- package/dist/browser/content/MapViewFrame.js.map +1 -0
- package/dist/browser/content/index.js +5 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/map-palette.js +39 -0
- package/dist/browser/content/map-palette.js.map +1 -0
- package/dist/browser/content/map-style.js +276 -0
- package/dist/browser/content/map-style.js.map +1 -0
- package/dist/browser/content/map-view-geometry.js +269 -0
- package/dist/browser/content/map-view-geometry.js.map +1 -0
- package/dist/browser/content/map-view-live.js +28 -0
- package/dist/browser/content/map-view-live.js.map +1 -0
- package/dist/browser/content/map-view-messages.js +53 -0
- package/dist/browser/content/map-view-messages.js.map +1 -0
- package/dist/browser/content/map-view-types.js +2 -0
- package/dist/browser/content/map-view-types.js.map +1 -0
- package/dist/browser/content/map-view-worker.js +10 -0
- package/dist/browser/feedback/dialog-core.js +19 -0
- package/dist/browser/feedback/dialog-core.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +17 -9
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +114 -8
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/app-workspace-width.js +26 -0
- package/dist/browser/layout/app-workspace-width.js.map +1 -0
- package/dist/browser/layout/index.js +1 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/licenses/maplibre-gl.txt +116 -0
- package/dist/ssr/actions/Toolbar.js +2 -0
- package/dist/ssr/actions/Toolbar.js.map +1 -1
- package/dist/ssr/chat/ChatDecision.js +11 -0
- package/dist/ssr/chat/ChatDecision.js.map +1 -1
- package/dist/ssr/content/MapAttribution.js +19 -0
- package/dist/ssr/content/MapAttribution.js.map +1 -0
- package/dist/ssr/content/MapView.js +474 -0
- package/dist/ssr/content/MapView.js.map +1 -0
- package/dist/ssr/content/MapViewFrame.js +193 -0
- package/dist/ssr/content/MapViewFrame.js.map +1 -0
- package/dist/ssr/content/index.js +5 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/map-palette.js +39 -0
- package/dist/ssr/content/map-palette.js.map +1 -0
- package/dist/ssr/content/map-style.js +276 -0
- package/dist/ssr/content/map-style.js.map +1 -0
- package/dist/ssr/content/map-view-geometry.js +269 -0
- package/dist/ssr/content/map-view-geometry.js.map +1 -0
- package/dist/ssr/content/map-view-live.js +1 -0
- package/dist/ssr/content/map-view-messages.js +53 -0
- package/dist/ssr/content/map-view-messages.js.map +1 -0
- package/dist/ssr/content/map-view-types.js +2 -0
- package/dist/ssr/content/map-view-types.js.map +1 -0
- package/dist/ssr/feedback/dialog-core.js +19 -0
- package/dist/ssr/feedback/dialog-core.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +17 -9
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +114 -8
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/app-workspace-width.js +26 -0
- package/dist/ssr/layout/app-workspace-width.js.map +1 -0
- package/dist/ssr/layout/index.js +1 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/content/MapAttribution.d.ts +6 -0
- package/dist/types/content/MapView.d.ts +5 -0
- package/dist/types/content/MapViewFrame.d.ts +31 -0
- package/dist/types/content/index.d.ts +6 -0
- package/dist/types/content/map-palette.d.ts +58 -0
- package/dist/types/content/map-style.d.ts +29 -0
- package/dist/types/content/map-view-geometry.d.ts +55 -0
- package/dist/types/content/map-view-live.d.ts +2 -0
- package/dist/types/content/map-view-messages.d.ts +21 -0
- package/dist/types/content/map-view-types.d.ts +61 -0
- package/dist/types/feedback/dialog-core.d.ts +1 -0
- package/dist/types/layout/AppWorkspace.d.ts +7 -3
- package/dist/types/layout/app-workspace-width.d.ts +13 -0
- package/dist/types/layout/index.d.ts +2 -2
- package/map-glyphs/IBM Plex Sans Medium/0-255.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/1024-1279.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/256-511.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/512-767.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/768-1023.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/7680-7935.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/8192-8447.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/8448-8703.pbf +0 -0
- package/map-glyphs/IBM Plex Sans Medium/8704-8959.pbf +0 -0
- package/map-glyphs/OFL.txt +93 -0
- package/package.json +10 -5
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
2
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
3
|
+
import { escape as _$escape } from "solid-js/web";
|
|
4
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
5
|
+
var _tmpl$ = ["<a", " target=\"_blank\" rel=\"noopener noreferrer\">", "</a>"];
|
|
6
|
+
import { For } from "solid-js";
|
|
7
|
+
import { mapAttribution } from "./map-style";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The required credits for maps built with `mapStyle()`, each one a link, for MapView's `attribution` slot.
|
|
11
|
+
* @example <MapView style={style} attribution={<MapAttribution />} height={320} />
|
|
12
|
+
*/
|
|
13
|
+
export function MapAttribution() {
|
|
14
|
+
return _$createComponent(For, {
|
|
15
|
+
each: mapAttribution,
|
|
16
|
+
children: (part, index) => [index() > 0 ? " · " : "", _$ssr(_tmpl$, _$ssrAttribute("href", _$escape(part.href, true), false), _$escape(part.label))]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=MapAttribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/MapAttribution.tsx"],"sourcesContent":["import { For, type JSX } from \"solid-js\";\nimport { mapAttribution } from \"./map-style\";\n\n/**\n * The required credits for maps built with `mapStyle()`, each one a link, for MapView's `attribution` slot.\n * @example <MapView style={style} attribution={<MapAttribution />} height={320} />\n */\nexport function MapAttribution(): JSX.Element {\n return (\n <For each={mapAttribution}>\n {(part, index) => (\n <>\n {index() > 0 ? \" · \" : \"\"}\n <a href={part.href} target=\"_blank\" rel=\"noopener noreferrer\">\n {part.label}\n </a>\n </>\n )}\n </For>\n );\n}\n"],"mappings":";;;;;AAAA,SAAS,GAAG,QAAkB,UAAU;AACxC,SAAS,cAAc,QAAQ,aAAa;;AAE5C;AACA;AACA;AACA;AACA,OAAO,SAAS,cAAc,GAAgB;EAC5C,yBACG,GAAG;IAAC,IAAI,EAAE,cAAc;IAAA,UACtB,CAAC,IAAI,EAAE,KAAK,MAER,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,EAAE,gDAChB,IAAI,CAAC,IAAI,0BACf,IAAI,CAAC,KAAK;EAGhB;AAGP","ignoreList":[]}
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { mergeProps as _$mergeProps } from "solid-js/web";
|
|
2
|
+
import { memo as _$memo } from "solid-js/web";
|
|
3
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
4
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
5
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
6
|
+
import { ssrStyleProperty as _$ssrStyleProperty } from "solid-js/web";
|
|
7
|
+
import { escape as _$escape } from "solid-js/web";
|
|
8
|
+
var _tmpl$ = ["<div class=\"k2b-map-view__notice\">", "</div>"],
|
|
9
|
+
_tmpl$2 = ["<div class=\"k2b-map-view__status\" role=\"status\"><i aria-hidden=\"true\"", "></i><span>", "</span>", "</div>"],
|
|
10
|
+
_tmpl$3 = "<i class=\"ti ti-plus\" aria-hidden=\"true\"></i>",
|
|
11
|
+
_tmpl$4 = "<i class=\"ti ti-minus\" aria-hidden=\"true\"></i>",
|
|
12
|
+
_tmpl$5 = "<i class=\"ti ti-current-location\" aria-hidden=\"true\"></i>",
|
|
13
|
+
_tmpl$6 = ["<div class=\"", "\" style=\"", "\"", " role=\"region\"", "><span class=\"k2b-sr-only\">", "</span><div class=\"k2b-map-view__live\"></div>", "<div class=\"k2b-map-view__messages\">", "", "</div><div class=\"k2b-map-view__controls\"><div class=\"k2b-map-view__zoom\">", "", "</div>", "</div><div class=\"k2b-map-view__foot\"><div class=\"k2b-map-view__info\" aria-live=\"polite\">", "</div>", "</div></div>"],
|
|
14
|
+
_tmpl$7 = ["<span>", "</span>"],
|
|
15
|
+
_tmpl$8 = ["<div class=\"k2b-map-view__empty\">", "</div>"];
|
|
16
|
+
import { children, createEffect, createMemo, createSignal, on, onCleanup, onMount, Show, untrack } from "solid-js";
|
|
17
|
+
import { Button, IconButton } from "../actions/Button";
|
|
18
|
+
import { prefersReducedMotion } from "../motion";
|
|
19
|
+
import { MapFootRow, MapGeometry, referenceScale, selectedMarker } from "./MapViewFrame";
|
|
20
|
+
import { DEFAULT_PADDING, fitCamera, mapFrame, metersPerPixel, pinOffsets, scaleBar, sortMarkers, unprojectPoint } from "./map-view-geometry";
|
|
21
|
+
import { useMapViewMessages } from "./map-view-messages";
|
|
22
|
+
function supportsWebgl() {
|
|
23
|
+
try {
|
|
24
|
+
const canvas = document.createElement("canvas");
|
|
25
|
+
// MapLibre 6 draws with WebGL 2 only; a browser with just WebGL 1 gets the static frame and the notice.
|
|
26
|
+
const gl = canvas.getContext("webgl2");
|
|
27
|
+
if (!gl) return false;
|
|
28
|
+
gl.getExtension("WEBGL_lose_context")?.loseContext();
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A static server frame enhanced with a same-origin MapLibre worker only after it enters the viewport. */
|
|
36
|
+
export function MapView(props) {
|
|
37
|
+
const messages = useMapViewMessages();
|
|
38
|
+
const frame = createMemo(() => mapFrame(props, props.height, props.padding ?? DEFAULT_PADDING));
|
|
39
|
+
const selected = createMemo(() => selectedMarker(props.markers ?? [], props.selectedId));
|
|
40
|
+
const selectedId = createMemo(() => selected()?.id);
|
|
41
|
+
const notice = children(() => props.notice);
|
|
42
|
+
const empty = children(() => props.empty);
|
|
43
|
+
const [state, setState] = createSignal("static");
|
|
44
|
+
const [dark, setDark] = createSignal(false);
|
|
45
|
+
const [boxStyle, setBoxStyle] = createSignal();
|
|
46
|
+
const [liveScale, setLiveScale] = createSignal();
|
|
47
|
+
const [measuredWidth, setMeasuredWidth] = createSignal();
|
|
48
|
+
// The zoom the person chose, once they zoomed; pin separation follows it relative to the current fit.
|
|
49
|
+
const [chosenZoom, setChosenZoom] = createSignal();
|
|
50
|
+
const zoomFactor = createMemo(() => {
|
|
51
|
+
const zoom = chosenZoom();
|
|
52
|
+
const f = frame();
|
|
53
|
+
const width = measuredWidth();
|
|
54
|
+
if (zoom === undefined || !f || width === undefined) return 1;
|
|
55
|
+
return 2 ** (zoom - fitCamera(f, width, props.padding ?? DEFAULT_PADDING).zoom);
|
|
56
|
+
});
|
|
57
|
+
const [needsReload, setNeedsReload] = createSignal(false);
|
|
58
|
+
// The server picks the scale bar for the widest fit; once the width is known, the bar names a distance that fits it.
|
|
59
|
+
const scale = createMemo(() => {
|
|
60
|
+
const f = frame();
|
|
61
|
+
if (!f) return undefined;
|
|
62
|
+
const live = liveScale();
|
|
63
|
+
if (live) return live;
|
|
64
|
+
const width = measuredWidth();
|
|
65
|
+
if (width === undefined) return referenceScale(f, props.padding ?? DEFAULT_PADDING);
|
|
66
|
+
const camera = fitCamera(f, width, props.padding ?? DEFAULT_PADDING);
|
|
67
|
+
const mpp = metersPerPixel(camera.center[1], camera.zoom);
|
|
68
|
+
const bar = scaleBar(mpp);
|
|
69
|
+
return {
|
|
70
|
+
label: bar.label,
|
|
71
|
+
width: `${bar.meters / mpp}px`
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
const resolvedStyle = () => {
|
|
75
|
+
const source = props.style;
|
|
76
|
+
return typeof source === "object" && "dark" in source ? dark() ? source.dark : source.light : source;
|
|
77
|
+
};
|
|
78
|
+
let root;
|
|
79
|
+
let live;
|
|
80
|
+
let info;
|
|
81
|
+
let map;
|
|
82
|
+
let currentStyle;
|
|
83
|
+
let disposed = false;
|
|
84
|
+
let visible = false;
|
|
85
|
+
let mounted = false;
|
|
86
|
+
let touched = false;
|
|
87
|
+
let replacingStyle = false;
|
|
88
|
+
let generation = 0;
|
|
89
|
+
let intersection;
|
|
90
|
+
let resize;
|
|
91
|
+
let infoResize;
|
|
92
|
+
const themes = [];
|
|
93
|
+
|
|
94
|
+
// From the person's first camera change on, the camera stays theirs; pin separation follows its zoom.
|
|
95
|
+
const touch = () => {
|
|
96
|
+
touched = true;
|
|
97
|
+
if (map) setChosenZoom(map.getZoom());
|
|
98
|
+
};
|
|
99
|
+
const removeMap = () => {
|
|
100
|
+
generation++;
|
|
101
|
+
const previous = map;
|
|
102
|
+
map = undefined;
|
|
103
|
+
previous?.remove();
|
|
104
|
+
setBoxStyle(undefined);
|
|
105
|
+
setLiveScale(undefined);
|
|
106
|
+
setChosenZoom(undefined);
|
|
107
|
+
currentStyle = undefined;
|
|
108
|
+
replacingStyle = false;
|
|
109
|
+
};
|
|
110
|
+
// MapLibre wraps its center across the antimeridian; geometry is drawn in the world copy nearest the camera.
|
|
111
|
+
const worldCopy = (live, f) => Math.round((live.getCenter().lng + 180) / 360 - (f.minX + f.spanX / 2));
|
|
112
|
+
const syncOverlay = () => {
|
|
113
|
+
const f = frame();
|
|
114
|
+
if (!map || !f || state() !== "ready") return;
|
|
115
|
+
const copy = worldCopy(map, f);
|
|
116
|
+
const a = unprojectPoint(f.minX + copy, f.minY);
|
|
117
|
+
const b = unprojectPoint(f.minX + copy + f.spanX, f.minY + f.spanY);
|
|
118
|
+
const top = map.project([a.lon, a.lat]);
|
|
119
|
+
const bottom = map.project([b.lon, b.lat]);
|
|
120
|
+
setBoxStyle({
|
|
121
|
+
left: `${top.x}px`,
|
|
122
|
+
top: `${top.y}px`,
|
|
123
|
+
width: `${bottom.x - top.x}px`,
|
|
124
|
+
height: `${bottom.y - top.y}px`,
|
|
125
|
+
transform: "none"
|
|
126
|
+
});
|
|
127
|
+
const mpp = metersPerPixel(map.getCenter().lat, map.getZoom());
|
|
128
|
+
const bar = scaleBar(mpp);
|
|
129
|
+
setLiveScale({
|
|
130
|
+
label: bar.label,
|
|
131
|
+
width: `${bar.meters / mpp}px`
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
const refit = () => {
|
|
135
|
+
const f = frame();
|
|
136
|
+
if (map && f && !touched) map.jumpTo(fitCamera(f, root.clientWidth, props.padding ?? DEFAULT_PADDING));
|
|
137
|
+
syncOverlay();
|
|
138
|
+
};
|
|
139
|
+
const start = async () => {
|
|
140
|
+
if (disposed || !visible || !frame()) return;
|
|
141
|
+
removeMap();
|
|
142
|
+
touched = false;
|
|
143
|
+
if (!supportsWebgl()) {
|
|
144
|
+
setState("no-webgl");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const attempt = generation;
|
|
148
|
+
setState("loading");
|
|
149
|
+
const fail = () => {
|
|
150
|
+
if (disposed || attempt !== generation) return;
|
|
151
|
+
removeMap();
|
|
152
|
+
setState("error");
|
|
153
|
+
};
|
|
154
|
+
let engine;
|
|
155
|
+
try {
|
|
156
|
+
engine = await import("./map-view-live");
|
|
157
|
+
} catch {
|
|
158
|
+
// The map code did not load, for example because the page outlived a release that removed its files.
|
|
159
|
+
// Importing the same address again cannot help; a reload fetches the current page and its map code.
|
|
160
|
+
if (disposed || attempt !== generation) return;
|
|
161
|
+
setNeedsReload(true);
|
|
162
|
+
fail();
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const {
|
|
167
|
+
createMap
|
|
168
|
+
} = engine;
|
|
169
|
+
if (disposed || attempt !== generation) return;
|
|
170
|
+
const f = frame();
|
|
171
|
+
if (!f) return;
|
|
172
|
+
currentStyle = resolvedStyle();
|
|
173
|
+
const t = messages();
|
|
174
|
+
const instance = createMap({
|
|
175
|
+
container: live,
|
|
176
|
+
style: currentStyle,
|
|
177
|
+
...fitCamera(f, root.clientWidth, props.padding ?? DEFAULT_PADDING),
|
|
178
|
+
attributionControl: false,
|
|
179
|
+
cooperativeGestures: true,
|
|
180
|
+
dragRotate: false,
|
|
181
|
+
// Shift-drag box zoom needs MapLibre's own stylesheet for its rectangle and starts without an input event.
|
|
182
|
+
boxZoom: false,
|
|
183
|
+
pitchWithRotate: false,
|
|
184
|
+
touchPitch: false,
|
|
185
|
+
maxPitch: 0,
|
|
186
|
+
bearing: 0,
|
|
187
|
+
pitch: 0,
|
|
188
|
+
keyboard: true,
|
|
189
|
+
trackResize: false,
|
|
190
|
+
// MapLibre's own gestures (keyboard and double-click zoom, inertia) follow the same choice as our buttons.
|
|
191
|
+
// The value is read when the map starts; MapLibre keeps one setting for all maps on the page.
|
|
192
|
+
reduceMotion: prefersReducedMotion(),
|
|
193
|
+
locale: {
|
|
194
|
+
"Map.Title": t.canvasTitle,
|
|
195
|
+
"CooperativeGesturesHandler.WindowsHelpText": t.gestureWindows,
|
|
196
|
+
"CooperativeGesturesHandler.MacHelpText": t.gestureMac,
|
|
197
|
+
"CooperativeGesturesHandler.MobileHelpText": t.gestureMobile
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
map = instance;
|
|
201
|
+
instance.on("error", event => {
|
|
202
|
+
// Tile and source errors name their source and leave the map usable; a style that does not load does not.
|
|
203
|
+
const styleFailed = !("sourceId" in event) && !("tile" in event);
|
|
204
|
+
if (styleFailed && (state() === "loading" || replacingStyle)) fail();
|
|
205
|
+
});
|
|
206
|
+
instance.on("style.load", () => {
|
|
207
|
+
replacingStyle = false;
|
|
208
|
+
});
|
|
209
|
+
instance.on("load", () => {
|
|
210
|
+
if (disposed || attempt !== generation) return;
|
|
211
|
+
setState("ready");
|
|
212
|
+
refit();
|
|
213
|
+
});
|
|
214
|
+
instance.on("movestart", event => {
|
|
215
|
+
if (event.originalEvent) touch();
|
|
216
|
+
});
|
|
217
|
+
instance.on("move", syncOverlay);
|
|
218
|
+
// Pin separation is decided again once a zoom ends, not on every animation frame.
|
|
219
|
+
instance.on("zoomend", () => {
|
|
220
|
+
if (map === instance && touched) setChosenZoom(instance.getZoom());
|
|
221
|
+
});
|
|
222
|
+
instance.on("resize", syncOverlay);
|
|
223
|
+
} catch {
|
|
224
|
+
fail();
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
const clearSelectedPin = () => {
|
|
228
|
+
const marker = selected();
|
|
229
|
+
if (!marker || state() !== "ready" || !map) return;
|
|
230
|
+
const f = frame();
|
|
231
|
+
const lon = marker.point.lon + (f ? worldCopy(map, f) * 360 : 0);
|
|
232
|
+
const p = map.project([lon, marker.point.lat]);
|
|
233
|
+
const offset = f ? pinOffsets(sortMarkers(props.markers ?? []), f, zoomFactor(), props.ownLocation?.point).get(marker.id) : undefined;
|
|
234
|
+
const x = p.x + (offset?.dx ?? 0);
|
|
235
|
+
const y = p.y + (offset?.dy ?? 0);
|
|
236
|
+
const w = root.clientWidth;
|
|
237
|
+
const h = root.clientHeight;
|
|
238
|
+
const tile = info.getBoundingClientRect();
|
|
239
|
+
const bounds = root.getBoundingClientRect();
|
|
240
|
+
const tileTop = tile.top - bounds.top - 8;
|
|
241
|
+
const covered = tile.height > 0 && x >= tile.left - bounds.left - 8 && x <= tile.right - bounds.left + 8 && y >= tileTop && y <= tile.bottom - bounds.top + 8;
|
|
242
|
+
if (!covered && x >= 16 && x <= w - 16 && y >= 16 && y <= h - 16) return;
|
|
243
|
+
touch();
|
|
244
|
+
// Put the drawn pin, offset included, in the free band above the tile.
|
|
245
|
+
const targetX = w / 2;
|
|
246
|
+
const targetY = tile.height > 0 ? tileTop / 2 : h / 2;
|
|
247
|
+
const target = map.unproject([x + w / 2 - targetX, y + h / 2 - targetY]);
|
|
248
|
+
const camera = {
|
|
249
|
+
center: [target.lng, target.lat]
|
|
250
|
+
};
|
|
251
|
+
if (prefersReducedMotion()) map.jumpTo(camera);else map.easeTo(camera);
|
|
252
|
+
};
|
|
253
|
+
onMount(() => {
|
|
254
|
+
mounted = true;
|
|
255
|
+
const theme = () => setDark(!!root.closest('.dark, .k2b-dark, [data-theme="dark"]'));
|
|
256
|
+
theme();
|
|
257
|
+
for (let ancestor = root; ancestor; ancestor = ancestor.parentElement) {
|
|
258
|
+
const observer = new MutationObserver(theme);
|
|
259
|
+
observer.observe(ancestor, {
|
|
260
|
+
attributes: true,
|
|
261
|
+
attributeFilter: ["class", "data-theme"]
|
|
262
|
+
});
|
|
263
|
+
themes.push(observer);
|
|
264
|
+
}
|
|
265
|
+
setMeasuredWidth(root.clientWidth);
|
|
266
|
+
resize = new ResizeObserver(() => {
|
|
267
|
+
setMeasuredWidth(root.clientWidth);
|
|
268
|
+
map?.resize();
|
|
269
|
+
refit();
|
|
270
|
+
});
|
|
271
|
+
resize.observe(root);
|
|
272
|
+
infoResize = new ResizeObserver(clearSelectedPin);
|
|
273
|
+
infoResize.observe(info);
|
|
274
|
+
const enter = () => {
|
|
275
|
+
visible = true;
|
|
276
|
+
intersection?.disconnect();
|
|
277
|
+
if (frame()) void start();
|
|
278
|
+
};
|
|
279
|
+
if (!frame()) setState("empty");
|
|
280
|
+
if (typeof IntersectionObserver === "undefined") enter();else {
|
|
281
|
+
intersection = new IntersectionObserver(entries => {
|
|
282
|
+
if (entries.some(entry => entry.isIntersecting)) enter();
|
|
283
|
+
}, {
|
|
284
|
+
threshold: 0,
|
|
285
|
+
rootMargin: "0px"
|
|
286
|
+
});
|
|
287
|
+
intersection.observe(root);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
createEffect(on(frame, value => {
|
|
291
|
+
if (!mounted) return;
|
|
292
|
+
if (!value) {
|
|
293
|
+
removeMap();
|
|
294
|
+
setState("empty");
|
|
295
|
+
} else if (state() === "empty") {
|
|
296
|
+
setState("static");
|
|
297
|
+
if (visible) void start();
|
|
298
|
+
} else refit();
|
|
299
|
+
}, {
|
|
300
|
+
defer: true
|
|
301
|
+
}));
|
|
302
|
+
createEffect(() => {
|
|
303
|
+
const style = resolvedStyle();
|
|
304
|
+
if (state() === "ready" && map && style !== currentStyle) {
|
|
305
|
+
currentStyle = style;
|
|
306
|
+
replacingStyle = true;
|
|
307
|
+
map.setStyle(style);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
createEffect(() => {
|
|
311
|
+
selected();
|
|
312
|
+
state();
|
|
313
|
+
untrack(clearSelectedPin);
|
|
314
|
+
});
|
|
315
|
+
onCleanup(() => {
|
|
316
|
+
disposed = true;
|
|
317
|
+
intersection?.disconnect();
|
|
318
|
+
resize?.disconnect();
|
|
319
|
+
infoResize?.disconnect();
|
|
320
|
+
for (const observer of themes) observer.disconnect();
|
|
321
|
+
removeMap();
|
|
322
|
+
});
|
|
323
|
+
const zoom = direction => {
|
|
324
|
+
if (!map || state() !== "ready") return;
|
|
325
|
+
touch();
|
|
326
|
+
const options = {
|
|
327
|
+
animate: !prefersReducedMotion()
|
|
328
|
+
};
|
|
329
|
+
if (direction === "in") map.zoomIn(options);else map.zoomOut(options);
|
|
330
|
+
};
|
|
331
|
+
return _$ssr(_tmpl$6, `k2b-map-view${props.class ? ` ${_$escape(props.class, true)}` : ""}`, _$ssrStyleProperty("height:", `${_$escape(props.height, true)}px`), _$ssrAttribute("data-state", _$escape(state(), true), false), _$ssrAttribute("aria-label", _$escape(messages().mapLabel, true), false), _$escape(messages().summary({
|
|
332
|
+
count: props.markers?.length ?? 0
|
|
333
|
+
})), _$escape(_$createComponent(Show, {
|
|
334
|
+
get when() {
|
|
335
|
+
return frame();
|
|
336
|
+
},
|
|
337
|
+
get fallback() {
|
|
338
|
+
return _$ssr(_tmpl$8, _$escape(_$createComponent(Show, {
|
|
339
|
+
get when() {
|
|
340
|
+
return empty();
|
|
341
|
+
},
|
|
342
|
+
get children() {
|
|
343
|
+
return _$ssr(_tmpl$7, _$escape(empty()));
|
|
344
|
+
}
|
|
345
|
+
})));
|
|
346
|
+
},
|
|
347
|
+
children: value => _$createComponent(MapGeometry, _$mergeProps(props, {
|
|
348
|
+
get frame() {
|
|
349
|
+
return value();
|
|
350
|
+
},
|
|
351
|
+
get boxStyle() {
|
|
352
|
+
return boxStyle();
|
|
353
|
+
},
|
|
354
|
+
get zoomFactor() {
|
|
355
|
+
return zoomFactor();
|
|
356
|
+
},
|
|
357
|
+
get onSelect() {
|
|
358
|
+
return props.onSelect;
|
|
359
|
+
},
|
|
360
|
+
interactive: true
|
|
361
|
+
}))
|
|
362
|
+
})), _$escape(_$createComponent(Show, {
|
|
363
|
+
get when() {
|
|
364
|
+
return notice();
|
|
365
|
+
},
|
|
366
|
+
get children() {
|
|
367
|
+
return _$ssr(_tmpl$, _$escape(notice()));
|
|
368
|
+
}
|
|
369
|
+
})), _$escape(_$createComponent(Show, {
|
|
370
|
+
get when() {
|
|
371
|
+
return state() === "loading" || state() === "error" || state() === "no-webgl";
|
|
372
|
+
},
|
|
373
|
+
get children() {
|
|
374
|
+
return _$ssr(_tmpl$2, _$ssrAttribute("class", state() === "loading" ? "ti ti-loader-2 k2b-spin" : state() === "error" ? "ti ti-alert-circle" : "ti ti-info-circle", false), state() === "loading" ? _$escape(messages().loading) : state() === "error" ? _$escape(messages().error) : _$escape(messages().noWebgl), _$escape(_$createComponent(Show, {
|
|
375
|
+
get when() {
|
|
376
|
+
return state() === "error";
|
|
377
|
+
},
|
|
378
|
+
get children() {
|
|
379
|
+
return _$createComponent(Button, {
|
|
380
|
+
size: "xs",
|
|
381
|
+
variant: "text",
|
|
382
|
+
onClick: () => needsReload() ? window.location.reload() : void start(),
|
|
383
|
+
get children() {
|
|
384
|
+
return needsReload() ? messages().reload : messages().retry;
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
})));
|
|
389
|
+
}
|
|
390
|
+
})), _$escape(_$createComponent(IconButton, {
|
|
391
|
+
get label() {
|
|
392
|
+
return messages().zoomIn;
|
|
393
|
+
},
|
|
394
|
+
tooltip: false,
|
|
395
|
+
get disabled() {
|
|
396
|
+
return state() !== "ready";
|
|
397
|
+
},
|
|
398
|
+
onClick: () => zoom("in"),
|
|
399
|
+
get children() {
|
|
400
|
+
return _$ssr(_tmpl$3);
|
|
401
|
+
}
|
|
402
|
+
})), _$escape(_$createComponent(IconButton, {
|
|
403
|
+
get label() {
|
|
404
|
+
return messages().zoomOut;
|
|
405
|
+
},
|
|
406
|
+
tooltip: false,
|
|
407
|
+
get disabled() {
|
|
408
|
+
return state() !== "ready";
|
|
409
|
+
},
|
|
410
|
+
onClick: () => zoom("out"),
|
|
411
|
+
get children() {
|
|
412
|
+
return _$ssr(_tmpl$4);
|
|
413
|
+
}
|
|
414
|
+
})), _$escape(_$createComponent(Show, {
|
|
415
|
+
get when() {
|
|
416
|
+
return props.onLocate;
|
|
417
|
+
},
|
|
418
|
+
get children() {
|
|
419
|
+
return _$createComponent(IconButton, {
|
|
420
|
+
"class": "k2b-map-view__locate",
|
|
421
|
+
tooltip: false,
|
|
422
|
+
get label() {
|
|
423
|
+
return messages().locate;
|
|
424
|
+
},
|
|
425
|
+
get ["aria-pressed"]() {
|
|
426
|
+
return !!props.ownLocation;
|
|
427
|
+
},
|
|
428
|
+
onClick: () => props.onLocate?.(),
|
|
429
|
+
get children() {
|
|
430
|
+
return _$ssr(_tmpl$5);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
})), _$escape(_$createComponent(Show, {
|
|
435
|
+
get when() {
|
|
436
|
+
return selectedId();
|
|
437
|
+
},
|
|
438
|
+
keyed: true,
|
|
439
|
+
children: _id => {
|
|
440
|
+
// Keep the tile's state and focus for this selection while its marker data refreshes.
|
|
441
|
+
const initial = selected();
|
|
442
|
+
const current = () => selected() ?? initial;
|
|
443
|
+
const marker = {
|
|
444
|
+
get id() {
|
|
445
|
+
return current().id;
|
|
446
|
+
},
|
|
447
|
+
get point() {
|
|
448
|
+
return current().point;
|
|
449
|
+
},
|
|
450
|
+
get mark() {
|
|
451
|
+
return current().mark;
|
|
452
|
+
},
|
|
453
|
+
get label() {
|
|
454
|
+
return current().label;
|
|
455
|
+
},
|
|
456
|
+
get tone() {
|
|
457
|
+
return current().tone;
|
|
458
|
+
},
|
|
459
|
+
get selected() {
|
|
460
|
+
return current().selected;
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
return props.infoTile?.(marker);
|
|
464
|
+
}
|
|
465
|
+
})), _$escape(_$createComponent(MapFootRow, {
|
|
466
|
+
get scale() {
|
|
467
|
+
return scale();
|
|
468
|
+
},
|
|
469
|
+
get children() {
|
|
470
|
+
return props.attribution;
|
|
471
|
+
}
|
|
472
|
+
})));
|
|
473
|
+
}
|
|
474
|
+
//# sourceMappingURL=MapView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/MapView.tsx"],"sourcesContent":["import type { Map as LiveMap } from \"maplibre-gl\";\nimport { children, createEffect, createMemo, createSignal, type JSX, on, onCleanup, onMount, Show, untrack } from \"solid-js\";\nimport { Button, IconButton } from \"../actions/Button\";\nimport { prefersReducedMotion } from \"../motion\";\nimport { MapFootRow, MapGeometry, type MapScale, referenceScale, selectedMarker } from \"./MapViewFrame\";\nimport {\n DEFAULT_PADDING,\n fitCamera,\n type MapFrame,\n mapFrame,\n metersPerPixel,\n pinOffsets,\n scaleBar,\n sortMarkers,\n unprojectPoint,\n} from \"./map-view-geometry\";\nimport { useMapViewMessages } from \"./map-view-messages\";\nimport type { MapViewMarker, MapViewProps, MapViewStyle } from \"./map-view-types\";\n\nexport type { MapViewProps } from \"./map-view-types\";\n\ntype MapState = \"static\" | \"loading\" | \"ready\" | \"error\" | \"no-webgl\" | \"empty\";\n\nfunction supportsWebgl(): boolean {\n try {\n const canvas = document.createElement(\"canvas\");\n // MapLibre 6 draws with WebGL 2 only; a browser with just WebGL 1 gets the static frame and the notice.\n const gl = canvas.getContext(\"webgl2\");\n if (!gl) return false;\n gl.getExtension(\"WEBGL_lose_context\")?.loseContext();\n return true;\n } catch {\n return false;\n }\n}\n\n/** A static server frame enhanced with a same-origin MapLibre worker only after it enters the viewport. */\nexport function MapView(props: MapViewProps): JSX.Element {\n const messages = useMapViewMessages();\n const frame = createMemo(() => mapFrame(props, props.height, props.padding ?? DEFAULT_PADDING));\n const selected = createMemo(() => selectedMarker(props.markers ?? [], props.selectedId));\n const selectedId = createMemo(() => selected()?.id);\n const notice = children(() => props.notice);\n const empty = children(() => props.empty);\n const [state, setState] = createSignal<MapState>(\"static\");\n const [dark, setDark] = createSignal(false);\n const [boxStyle, setBoxStyle] = createSignal<JSX.CSSProperties>();\n const [liveScale, setLiveScale] = createSignal<MapScale>();\n const [measuredWidth, setMeasuredWidth] = createSignal<number>();\n // The zoom the person chose, once they zoomed; pin separation follows it relative to the current fit.\n const [chosenZoom, setChosenZoom] = createSignal<number>();\n const zoomFactor = createMemo(() => {\n const zoom = chosenZoom();\n const f = frame();\n const width = measuredWidth();\n if (zoom === undefined || !f || width === undefined) return 1;\n return 2 ** (zoom - fitCamera(f, width, props.padding ?? DEFAULT_PADDING).zoom);\n });\n const [needsReload, setNeedsReload] = createSignal(false);\n // The server picks the scale bar for the widest fit; once the width is known, the bar names a distance that fits it.\n const scale = createMemo((): MapScale | undefined => {\n const f = frame();\n if (!f) return undefined;\n const live = liveScale();\n if (live) return live;\n const width = measuredWidth();\n if (width === undefined) return referenceScale(f, props.padding ?? DEFAULT_PADDING);\n const camera = fitCamera(f, width, props.padding ?? DEFAULT_PADDING);\n const mpp = metersPerPixel(camera.center[1], camera.zoom);\n const bar = scaleBar(mpp);\n return { label: bar.label, width: `${bar.meters / mpp}px` };\n });\n const resolvedStyle = (): MapViewStyle => {\n const source = props.style;\n return typeof source === \"object\" && \"dark\" in source ? (dark() ? source.dark : source.light) : source;\n };\n let root!: HTMLDivElement;\n let live!: HTMLDivElement;\n let info!: HTMLDivElement;\n let map: LiveMap | undefined;\n let currentStyle: MapViewStyle | undefined;\n let disposed = false;\n let visible = false;\n let mounted = false;\n let touched = false;\n let replacingStyle = false;\n let generation = 0;\n let intersection: IntersectionObserver | undefined;\n let resize: ResizeObserver | undefined;\n let infoResize: ResizeObserver | undefined;\n const themes: MutationObserver[] = [];\n\n // From the person's first camera change on, the camera stays theirs; pin separation follows its zoom.\n const touch = () => {\n touched = true;\n if (map) setChosenZoom(map.getZoom());\n };\n const removeMap = () => {\n generation++;\n const previous = map;\n map = undefined;\n previous?.remove();\n setBoxStyle(undefined);\n setLiveScale(undefined);\n setChosenZoom(undefined);\n currentStyle = undefined;\n replacingStyle = false;\n };\n // MapLibre wraps its center across the antimeridian; geometry is drawn in the world copy nearest the camera.\n const worldCopy = (live: LiveMap, f: MapFrame): number => Math.round((live.getCenter().lng + 180) / 360 - (f.minX + f.spanX / 2));\n const syncOverlay = () => {\n const f = frame();\n if (!map || !f || state() !== \"ready\") return;\n const copy = worldCopy(map, f);\n const a = unprojectPoint(f.minX + copy, f.minY);\n const b = unprojectPoint(f.minX + copy + f.spanX, f.minY + f.spanY);\n const top = map.project([a.lon, a.lat]);\n const bottom = map.project([b.lon, b.lat]);\n setBoxStyle({\n left: `${top.x}px`,\n top: `${top.y}px`,\n width: `${bottom.x - top.x}px`,\n height: `${bottom.y - top.y}px`,\n transform: \"none\",\n });\n const mpp = metersPerPixel(map.getCenter().lat, map.getZoom());\n const bar = scaleBar(mpp);\n setLiveScale({ label: bar.label, width: `${bar.meters / mpp}px` });\n };\n const refit = () => {\n const f = frame();\n if (map && f && !touched) map.jumpTo(fitCamera(f, root.clientWidth, props.padding ?? DEFAULT_PADDING));\n syncOverlay();\n };\n const start = async () => {\n if (disposed || !visible || !frame()) return;\n removeMap();\n touched = false;\n if (!supportsWebgl()) {\n setState(\"no-webgl\");\n return;\n }\n const attempt = generation;\n setState(\"loading\");\n const fail = () => {\n if (disposed || attempt !== generation) return;\n removeMap();\n setState(\"error\");\n };\n let engine: typeof import(\"./map-view-live\");\n try {\n engine = await import(\"./map-view-live\");\n } catch {\n // The map code did not load, for example because the page outlived a release that removed its files.\n // Importing the same address again cannot help; a reload fetches the current page and its map code.\n if (disposed || attempt !== generation) return;\n setNeedsReload(true);\n fail();\n return;\n }\n try {\n const { createMap } = engine;\n if (disposed || attempt !== generation) return;\n const f = frame();\n if (!f) return;\n currentStyle = resolvedStyle();\n const t = messages();\n const instance = createMap({\n container: live,\n style: currentStyle,\n ...fitCamera(f, root.clientWidth, props.padding ?? DEFAULT_PADDING),\n attributionControl: false,\n cooperativeGestures: true,\n dragRotate: false,\n // Shift-drag box zoom needs MapLibre's own stylesheet for its rectangle and starts without an input event.\n boxZoom: false,\n pitchWithRotate: false,\n touchPitch: false,\n maxPitch: 0,\n bearing: 0,\n pitch: 0,\n keyboard: true,\n trackResize: false,\n // MapLibre's own gestures (keyboard and double-click zoom, inertia) follow the same choice as our buttons.\n // The value is read when the map starts; MapLibre keeps one setting for all maps on the page.\n reduceMotion: prefersReducedMotion(),\n locale: {\n \"Map.Title\": t.canvasTitle,\n \"CooperativeGesturesHandler.WindowsHelpText\": t.gestureWindows,\n \"CooperativeGesturesHandler.MacHelpText\": t.gestureMac,\n \"CooperativeGesturesHandler.MobileHelpText\": t.gestureMobile,\n },\n });\n map = instance;\n instance.on(\"error\", (event) => {\n // Tile and source errors name their source and leave the map usable; a style that does not load does not.\n const styleFailed = !(\"sourceId\" in event) && !(\"tile\" in event);\n if (styleFailed && (state() === \"loading\" || replacingStyle)) fail();\n });\n instance.on(\"style.load\", () => {\n replacingStyle = false;\n });\n instance.on(\"load\", () => {\n if (disposed || attempt !== generation) return;\n setState(\"ready\");\n refit();\n });\n instance.on(\"movestart\", (event) => {\n if (event.originalEvent) touch();\n });\n instance.on(\"move\", syncOverlay);\n // Pin separation is decided again once a zoom ends, not on every animation frame.\n instance.on(\"zoomend\", () => {\n if (map === instance && touched) setChosenZoom(instance.getZoom());\n });\n instance.on(\"resize\", syncOverlay);\n } catch {\n fail();\n }\n };\n const clearSelectedPin = () => {\n const marker = selected();\n if (!marker || state() !== \"ready\" || !map) return;\n const f = frame();\n const lon = marker.point.lon + (f ? worldCopy(map, f) * 360 : 0);\n const p = map.project([lon, marker.point.lat]);\n const offset = f ? pinOffsets(sortMarkers(props.markers ?? []), f, zoomFactor(), props.ownLocation?.point).get(marker.id) : undefined;\n const x = p.x + (offset?.dx ?? 0);\n const y = p.y + (offset?.dy ?? 0);\n const w = root.clientWidth;\n const h = root.clientHeight;\n const tile = info.getBoundingClientRect();\n const bounds = root.getBoundingClientRect();\n const tileTop = tile.top - bounds.top - 8;\n const covered =\n tile.height > 0 &&\n x >= tile.left - bounds.left - 8 &&\n x <= tile.right - bounds.left + 8 &&\n y >= tileTop &&\n y <= tile.bottom - bounds.top + 8;\n if (!covered && x >= 16 && x <= w - 16 && y >= 16 && y <= h - 16) return;\n touch();\n // Put the drawn pin, offset included, in the free band above the tile.\n const targetX = w / 2;\n const targetY = tile.height > 0 ? tileTop / 2 : h / 2;\n const target = map.unproject([x + w / 2 - targetX, y + h / 2 - targetY]);\n const camera = { center: [target.lng, target.lat] satisfies [number, number] };\n if (prefersReducedMotion()) map.jumpTo(camera);\n else map.easeTo(camera);\n };\n onMount(() => {\n mounted = true;\n const theme = () => setDark(!!root.closest('.dark, .k2b-dark, [data-theme=\"dark\"]'));\n theme();\n for (let ancestor: Element | null = root; ancestor; ancestor = ancestor.parentElement) {\n const observer = new MutationObserver(theme);\n observer.observe(ancestor, { attributes: true, attributeFilter: [\"class\", \"data-theme\"] });\n themes.push(observer);\n }\n setMeasuredWidth(root.clientWidth);\n resize = new ResizeObserver(() => {\n setMeasuredWidth(root.clientWidth);\n map?.resize();\n refit();\n });\n resize.observe(root);\n infoResize = new ResizeObserver(clearSelectedPin);\n infoResize.observe(info);\n const enter = () => {\n visible = true;\n intersection?.disconnect();\n if (frame()) void start();\n };\n if (!frame()) setState(\"empty\");\n if (typeof IntersectionObserver === \"undefined\") enter();\n else {\n intersection = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) enter();\n },\n { threshold: 0, rootMargin: \"0px\" },\n );\n intersection.observe(root);\n }\n });\n createEffect(\n on(\n frame,\n (value) => {\n if (!mounted) return;\n if (!value) {\n removeMap();\n setState(\"empty\");\n } else if (state() === \"empty\") {\n setState(\"static\");\n if (visible) void start();\n } else refit();\n },\n { defer: true },\n ),\n );\n createEffect(() => {\n const style = resolvedStyle();\n if (state() === \"ready\" && map && style !== currentStyle) {\n currentStyle = style;\n replacingStyle = true;\n map.setStyle(style);\n }\n });\n createEffect(() => {\n selected();\n state();\n untrack(clearSelectedPin);\n });\n onCleanup(() => {\n disposed = true;\n intersection?.disconnect();\n resize?.disconnect();\n infoResize?.disconnect();\n for (const observer of themes) observer.disconnect();\n removeMap();\n });\n const zoom = (direction: \"in\" | \"out\") => {\n if (!map || state() !== \"ready\") return;\n touch();\n const options = { animate: !prefersReducedMotion() };\n if (direction === \"in\") map.zoomIn(options);\n else map.zoomOut(options);\n };\n return (\n <div\n ref={root}\n class={`k2b-map-view${props.class ? ` ${props.class}` : \"\"}`}\n style={{ height: `${props.height}px` }}\n data-state={state()}\n role=\"region\"\n aria-label={messages().mapLabel}\n >\n <span class=\"k2b-sr-only\">{messages().summary({ count: props.markers?.length ?? 0 })}</span>\n <div ref={live} class=\"k2b-map-view__live\" />\n <Show\n when={frame()}\n fallback={\n <div class=\"k2b-map-view__empty\">\n <Show when={empty()}>\n <span>{empty()}</span>\n </Show>\n </div>\n }\n >\n {(value) => (\n <MapGeometry {...props} frame={value()} boxStyle={boxStyle()} zoomFactor={zoomFactor()} onSelect={props.onSelect} interactive />\n )}\n </Show>\n <div class=\"k2b-map-view__messages\">\n <Show when={notice()}>\n <div class=\"k2b-map-view__notice\">{notice()}</div>\n </Show>\n <Show when={state() === \"loading\" || state() === \"error\" || state() === \"no-webgl\"}>\n <div class=\"k2b-map-view__status\" role=\"status\">\n <i\n aria-hidden=\"true\"\n class={state() === \"loading\" ? \"ti ti-loader-2 k2b-spin\" : state() === \"error\" ? \"ti ti-alert-circle\" : \"ti ti-info-circle\"}\n />\n <span>{state() === \"loading\" ? messages().loading : state() === \"error\" ? messages().error : messages().noWebgl}</span>\n <Show when={state() === \"error\"}>\n <Button size=\"xs\" variant=\"text\" onClick={() => (needsReload() ? window.location.reload() : void start())}>\n {needsReload() ? messages().reload : messages().retry}\n </Button>\n </Show>\n </div>\n </Show>\n </div>\n <div class=\"k2b-map-view__controls\">\n <div class=\"k2b-map-view__zoom\">\n <IconButton label={messages().zoomIn} tooltip={false} disabled={state() !== \"ready\"} onClick={() => zoom(\"in\")}>\n <i class=\"ti ti-plus\" aria-hidden=\"true\" />\n </IconButton>\n <IconButton label={messages().zoomOut} tooltip={false} disabled={state() !== \"ready\"} onClick={() => zoom(\"out\")}>\n <i class=\"ti ti-minus\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n <Show when={props.onLocate}>\n <IconButton\n class=\"k2b-map-view__locate\"\n tooltip={false}\n label={messages().locate}\n aria-pressed={!!props.ownLocation}\n onClick={() => props.onLocate?.()}\n >\n <i class=\"ti ti-current-location\" aria-hidden=\"true\" />\n </IconButton>\n </Show>\n </div>\n <div class=\"k2b-map-view__foot\">\n <div ref={info} class=\"k2b-map-view__info\" aria-live=\"polite\">\n <Show when={selectedId()} keyed>\n {(_id) => {\n // Keep the tile's state and focus for this selection while its marker data refreshes.\n const initial = selected();\n const current = () => selected() ?? initial;\n const marker: MapViewMarker = {\n get id() {\n return current()!.id;\n },\n get point() {\n return current()!.point;\n },\n get mark() {\n return current()!.mark;\n },\n get label() {\n return current()!.label;\n },\n get tone() {\n return current()!.tone;\n },\n get selected() {\n return current()!.selected;\n },\n };\n return props.infoTile?.(marker);\n }}\n </Show>\n </div>\n <MapFootRow scale={scale()}>{props.attribution}</MapFootRow>\n </div>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|