@k2b/ui 0.30.0 → 0.32.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/base.css +2 -0
- package/dist/browser/actions/Toolbar.js +2 -0
- package/dist/browser/actions/Toolbar.js.map +1 -1
- package/dist/browser/actions/ViewTabs.js +8 -0
- package/dist/browser/actions/ViewTabs.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/Chart.js +104 -55
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/ChartExplorer.js +5 -3
- package/dist/browser/content/ChartExplorer.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/chart-inspection-core.js +4 -1
- package/dist/browser/content/chart-inspection-core.js.map +1 -1
- package/dist/browser/content/code-highlight.js +66 -0
- package/dist/browser/content/code-highlight.js.map +1 -1
- package/dist/browser/content/index.js +6 -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 +65 -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/inputs/AutocompleteEditor.js +167 -104
- package/dist/browser/inputs/AutocompleteEditor.js.map +1 -1
- package/dist/browser/inputs/RichSelect.js +1474 -0
- package/dist/browser/inputs/RichSelect.js.map +1 -0
- package/dist/browser/inputs/TextInput.js +95 -60
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/inputs/choice.js +19 -8
- package/dist/browser/inputs/choice.js.map +1 -1
- package/dist/browser/inputs/index.js +1 -0
- package/dist/browser/inputs/index.js.map +1 -1
- package/dist/browser/inputs/rich-select-messages.js +46 -0
- package/dist/browser/inputs/rich-select-messages.js.map +1 -0
- package/dist/browser/layout/AppWorkspace.js +194 -144
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/DetailPanel.js +10 -1
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/Navigation.js +14 -5
- package/dist/browser/layout/Navigation.js.map +1 -1
- package/dist/browser/layout/PageTitle.js +9 -3
- package/dist/browser/layout/PageTitle.js.map +1 -1
- package/dist/browser/layout/ResizeSeparator.js +8 -2
- package/dist/browser/layout/ResizeSeparator.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +301 -34
- 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/browser/layout/navigation-model.js.map +1 -1
- package/dist/browser/layout/resize-separator.js +25 -1
- package/dist/browser/layout/resize-separator.js.map +1 -1
- package/dist/browser/surfaces/Skeleton.js +14 -0
- package/dist/browser/surfaces/Skeleton.js.map +1 -0
- package/dist/browser/surfaces/index.js +1 -0
- package/dist/browser/surfaces/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/actions/ViewTabs.js +8 -0
- package/dist/ssr/actions/ViewTabs.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/Chart.js +27 -7
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/ChartExplorer.js +5 -3
- package/dist/ssr/content/ChartExplorer.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/chart-inspection-core.js +4 -1
- package/dist/ssr/content/chart-inspection-core.js.map +1 -1
- package/dist/ssr/content/code-highlight.js +66 -0
- package/dist/ssr/content/code-highlight.js.map +1 -1
- package/dist/ssr/content/index.js +6 -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/inputs/AutocompleteEditor.js +64 -24
- package/dist/ssr/inputs/AutocompleteEditor.js.map +1 -1
- package/dist/ssr/inputs/RichSelect.js +950 -0
- package/dist/ssr/inputs/RichSelect.js.map +1 -0
- package/dist/ssr/inputs/TextInput.js +40 -16
- package/dist/ssr/inputs/TextInput.js.map +1 -1
- package/dist/ssr/inputs/choice.js +19 -8
- package/dist/ssr/inputs/choice.js.map +1 -1
- package/dist/ssr/inputs/index.js +1 -0
- package/dist/ssr/inputs/index.js.map +1 -1
- package/dist/ssr/inputs/rich-select-messages.js +46 -0
- package/dist/ssr/inputs/rich-select-messages.js.map +1 -0
- package/dist/ssr/layout/AppWorkspace.js +53 -16
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/DetailPanel.js +1 -1
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/Navigation.js +1 -1
- package/dist/ssr/layout/Navigation.js.map +1 -1
- package/dist/ssr/layout/PageTitle.js +9 -3
- package/dist/ssr/layout/PageTitle.js.map +1 -1
- package/dist/ssr/layout/ResizeSeparator.js +4 -1
- package/dist/ssr/layout/ResizeSeparator.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +301 -34
- 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/ssr/layout/navigation-model.js.map +1 -1
- package/dist/ssr/layout/resize-separator.js +25 -1
- package/dist/ssr/layout/resize-separator.js.map +1 -1
- package/dist/ssr/surfaces/Skeleton.js +8 -0
- package/dist/ssr/surfaces/Skeleton.js.map +1 -0
- package/dist/ssr/surfaces/index.js +1 -0
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/content/Chart.d.ts +4 -2
- package/dist/types/content/ChartExplorer.d.ts +0 -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/code-highlight.d.ts +3 -1
- package/dist/types/content/index.d.ts +7 -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 +63 -0
- package/dist/types/feedback/dialog-core.d.ts +1 -0
- package/dist/types/inputs/AutocompleteEditor.d.ts +6 -1
- package/dist/types/inputs/RichSelect.d.ts +93 -0
- package/dist/types/inputs/TextInput.d.ts +5 -2
- package/dist/types/inputs/choice.d.ts +24 -4
- package/dist/types/inputs/index.d.ts +2 -0
- package/dist/types/inputs/rich-select-messages.d.ts +21 -0
- package/dist/types/layout/AppWorkspace.d.ts +14 -3
- package/dist/types/layout/DetailPanel.d.ts +2 -0
- package/dist/types/layout/app-workspace-controller.d.ts +2 -0
- package/dist/types/layout/app-workspace-width.d.ts +13 -0
- package/dist/types/layout/index.d.ts +2 -2
- package/dist/types/layout/navigation-model.d.ts +2 -0
- package/dist/types/layout/resize-separator.d.ts +1 -0
- package/dist/types/surfaces/Skeleton.d.ts +6 -0
- package/dist/types/surfaces/index.d.ts +1 -0
- 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 +11 -6
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import { template as _$template } from "solid-js/web";
|
|
2
|
+
import { mergeProps as _$mergeProps } from "solid-js/web";
|
|
3
|
+
import { setAttribute as _$setAttribute } from "solid-js/web";
|
|
4
|
+
import { setStyleProperty as _$setStyleProperty } from "solid-js/web";
|
|
5
|
+
import { className as _$className } from "solid-js/web";
|
|
6
|
+
import { effect as _$effect } from "solid-js/web";
|
|
7
|
+
import { getNextMarker as _$getNextMarker } from "solid-js/web";
|
|
8
|
+
import { memo as _$memo } from "solid-js/web";
|
|
9
|
+
import { getNextElement as _$getNextElement } from "solid-js/web";
|
|
10
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
11
|
+
import { insert as _$insert } from "solid-js/web";
|
|
12
|
+
import { use as _$use } from "solid-js/web";
|
|
13
|
+
var _tmpl$ = /*#__PURE__*/_$template(`<div class=k2b-map-view__notice>`),
|
|
14
|
+
_tmpl$2 = /*#__PURE__*/_$template(`<div class=k2b-map-view__status role=status><i aria-hidden=true></i><span></span><!$><!/>`),
|
|
15
|
+
_tmpl$3 = /*#__PURE__*/_$template(`<i class="ti ti-plus"aria-hidden=true>`),
|
|
16
|
+
_tmpl$4 = /*#__PURE__*/_$template(`<i class="ti ti-minus"aria-hidden=true>`),
|
|
17
|
+
_tmpl$5 = /*#__PURE__*/_$template(`<i class="ti ti-current-location"aria-hidden=true>`),
|
|
18
|
+
_tmpl$6 = /*#__PURE__*/_$template(`<div 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><!$><!/>`),
|
|
19
|
+
_tmpl$7 = /*#__PURE__*/_$template(`<span>`),
|
|
20
|
+
_tmpl$8 = /*#__PURE__*/_$template(`<div class=k2b-map-view__empty>`);
|
|
21
|
+
import { children, createEffect, createMemo, createSignal, on, onCleanup, onMount, Show, untrack } from "solid-js";
|
|
22
|
+
import { Button, IconButton } from "../actions/Button";
|
|
23
|
+
import { prefersReducedMotion } from "../motion";
|
|
24
|
+
import { MapFootRow, MapGeometry, referenceScale, selectedMarker } from "./MapViewFrame";
|
|
25
|
+
import { DEFAULT_PADDING, fitCamera, mapFrame, metersPerPixel, pinOffsets, scaleBar, sortMarkers, unprojectPoint } from "./map-view-geometry";
|
|
26
|
+
import { useMapViewMessages } from "./map-view-messages";
|
|
27
|
+
function supportsWebgl() {
|
|
28
|
+
try {
|
|
29
|
+
const canvas = document.createElement("canvas");
|
|
30
|
+
// MapLibre 6 draws with WebGL 2 only; a browser with just WebGL 1 gets the static frame and the notice.
|
|
31
|
+
const gl = canvas.getContext("webgl2");
|
|
32
|
+
if (!gl) return false;
|
|
33
|
+
gl.getExtension("WEBGL_lose_context")?.loseContext();
|
|
34
|
+
return true;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A static server frame enhanced with a same-origin MapLibre worker only after it enters the viewport. */
|
|
41
|
+
export function MapView(props) {
|
|
42
|
+
const messages = useMapViewMessages();
|
|
43
|
+
const frame = createMemo(() => mapFrame(props, props.height, props.padding ?? DEFAULT_PADDING));
|
|
44
|
+
const selected = createMemo(() => selectedMarker(props.markers ?? [], props.selectedId));
|
|
45
|
+
const selectedId = createMemo(() => selected()?.id);
|
|
46
|
+
const notice = children(() => props.notice);
|
|
47
|
+
const empty = children(() => props.empty);
|
|
48
|
+
const [state, setState] = createSignal("static");
|
|
49
|
+
createEffect(() => props.onStateChange?.(state()));
|
|
50
|
+
const [dark, setDark] = createSignal(false);
|
|
51
|
+
const [boxStyle, setBoxStyle] = createSignal();
|
|
52
|
+
const [liveScale, setLiveScale] = createSignal();
|
|
53
|
+
const [measuredWidth, setMeasuredWidth] = createSignal();
|
|
54
|
+
// The zoom the person chose, once they zoomed; pin separation follows it relative to the current fit.
|
|
55
|
+
const [chosenZoom, setChosenZoom] = createSignal();
|
|
56
|
+
const zoomFactor = createMemo(() => {
|
|
57
|
+
const zoom = chosenZoom();
|
|
58
|
+
const f = frame();
|
|
59
|
+
const width = measuredWidth();
|
|
60
|
+
if (zoom === undefined || !f || width === undefined) return 1;
|
|
61
|
+
return 2 ** (zoom - fitCamera(f, width, props.padding ?? DEFAULT_PADDING).zoom);
|
|
62
|
+
});
|
|
63
|
+
const [needsReload, setNeedsReload] = createSignal(false);
|
|
64
|
+
// The server picks the scale bar for the widest fit; once the width is known, the bar names a distance that fits it.
|
|
65
|
+
const scale = createMemo(() => {
|
|
66
|
+
const f = frame();
|
|
67
|
+
if (!f) return undefined;
|
|
68
|
+
const live = liveScale();
|
|
69
|
+
if (live) return live;
|
|
70
|
+
const width = measuredWidth();
|
|
71
|
+
if (width === undefined) return referenceScale(f, props.padding ?? DEFAULT_PADDING);
|
|
72
|
+
const camera = fitCamera(f, width, props.padding ?? DEFAULT_PADDING);
|
|
73
|
+
const mpp = metersPerPixel(camera.center[1], camera.zoom);
|
|
74
|
+
const bar = scaleBar(mpp);
|
|
75
|
+
return {
|
|
76
|
+
label: bar.label,
|
|
77
|
+
width: `${bar.meters / mpp}px`
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
const resolvedStyle = () => {
|
|
81
|
+
const source = props.style;
|
|
82
|
+
return typeof source === "object" && "dark" in source ? dark() ? source.dark : source.light : source;
|
|
83
|
+
};
|
|
84
|
+
let root;
|
|
85
|
+
let live;
|
|
86
|
+
let info;
|
|
87
|
+
let map;
|
|
88
|
+
let currentStyle;
|
|
89
|
+
let disposed = false;
|
|
90
|
+
let visible = false;
|
|
91
|
+
let mounted = false;
|
|
92
|
+
let touched = false;
|
|
93
|
+
let replacingStyle = false;
|
|
94
|
+
let generation = 0;
|
|
95
|
+
let intersection;
|
|
96
|
+
let resize;
|
|
97
|
+
let infoResize;
|
|
98
|
+
const themes = [];
|
|
99
|
+
|
|
100
|
+
// From the person's first camera change on, the camera stays theirs; pin separation follows its zoom.
|
|
101
|
+
const touch = () => {
|
|
102
|
+
touched = true;
|
|
103
|
+
if (map) setChosenZoom(map.getZoom());
|
|
104
|
+
};
|
|
105
|
+
const removeMap = () => {
|
|
106
|
+
generation++;
|
|
107
|
+
const previous = map;
|
|
108
|
+
map = undefined;
|
|
109
|
+
previous?.remove();
|
|
110
|
+
setBoxStyle(undefined);
|
|
111
|
+
setLiveScale(undefined);
|
|
112
|
+
setChosenZoom(undefined);
|
|
113
|
+
currentStyle = undefined;
|
|
114
|
+
replacingStyle = false;
|
|
115
|
+
};
|
|
116
|
+
// MapLibre wraps its center across the antimeridian; geometry is drawn in the world copy nearest the camera.
|
|
117
|
+
const worldCopy = (live, f) => Math.round((live.getCenter().lng + 180) / 360 - (f.minX + f.spanX / 2));
|
|
118
|
+
const syncOverlay = () => {
|
|
119
|
+
const f = frame();
|
|
120
|
+
if (!map || !f || state() !== "ready") return;
|
|
121
|
+
const copy = worldCopy(map, f);
|
|
122
|
+
const a = unprojectPoint(f.minX + copy, f.minY);
|
|
123
|
+
const b = unprojectPoint(f.minX + copy + f.spanX, f.minY + f.spanY);
|
|
124
|
+
const top = map.project([a.lon, a.lat]);
|
|
125
|
+
const bottom = map.project([b.lon, b.lat]);
|
|
126
|
+
setBoxStyle({
|
|
127
|
+
left: `${top.x}px`,
|
|
128
|
+
top: `${top.y}px`,
|
|
129
|
+
width: `${bottom.x - top.x}px`,
|
|
130
|
+
height: `${bottom.y - top.y}px`,
|
|
131
|
+
transform: "none"
|
|
132
|
+
});
|
|
133
|
+
const mpp = metersPerPixel(map.getCenter().lat, map.getZoom());
|
|
134
|
+
const bar = scaleBar(mpp);
|
|
135
|
+
setLiveScale({
|
|
136
|
+
label: bar.label,
|
|
137
|
+
width: `${bar.meters / mpp}px`
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
const refit = () => {
|
|
141
|
+
const f = frame();
|
|
142
|
+
if (map && f && !touched) map.jumpTo(fitCamera(f, root.clientWidth, props.padding ?? DEFAULT_PADDING));
|
|
143
|
+
syncOverlay();
|
|
144
|
+
};
|
|
145
|
+
const start = async () => {
|
|
146
|
+
if (disposed || !visible || !frame()) return;
|
|
147
|
+
removeMap();
|
|
148
|
+
touched = false;
|
|
149
|
+
if (!supportsWebgl()) {
|
|
150
|
+
setState("no-webgl");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const attempt = generation;
|
|
154
|
+
setState("loading");
|
|
155
|
+
const fail = () => {
|
|
156
|
+
if (disposed || attempt !== generation) return;
|
|
157
|
+
removeMap();
|
|
158
|
+
setState("error");
|
|
159
|
+
};
|
|
160
|
+
let engine;
|
|
161
|
+
try {
|
|
162
|
+
engine = await import("./map-view-live");
|
|
163
|
+
} catch {
|
|
164
|
+
// The map code did not load, for example because the page outlived a release that removed its files.
|
|
165
|
+
// Importing the same address again cannot help; a reload fetches the current page and its map code.
|
|
166
|
+
if (disposed || attempt !== generation) return;
|
|
167
|
+
setNeedsReload(true);
|
|
168
|
+
fail();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const {
|
|
173
|
+
createMap
|
|
174
|
+
} = engine;
|
|
175
|
+
if (disposed || attempt !== generation) return;
|
|
176
|
+
const f = frame();
|
|
177
|
+
if (!f) return;
|
|
178
|
+
currentStyle = resolvedStyle();
|
|
179
|
+
const t = messages();
|
|
180
|
+
const instance = createMap({
|
|
181
|
+
container: live,
|
|
182
|
+
style: currentStyle,
|
|
183
|
+
...fitCamera(f, root.clientWidth, props.padding ?? DEFAULT_PADDING),
|
|
184
|
+
attributionControl: false,
|
|
185
|
+
cooperativeGestures: true,
|
|
186
|
+
dragRotate: false,
|
|
187
|
+
// Shift-drag box zoom needs MapLibre's own stylesheet for its rectangle and starts without an input event.
|
|
188
|
+
boxZoom: false,
|
|
189
|
+
pitchWithRotate: false,
|
|
190
|
+
touchPitch: false,
|
|
191
|
+
maxPitch: 0,
|
|
192
|
+
bearing: 0,
|
|
193
|
+
pitch: 0,
|
|
194
|
+
keyboard: true,
|
|
195
|
+
trackResize: false,
|
|
196
|
+
// MapLibre's own gestures (keyboard and double-click zoom, inertia) follow the same choice as our buttons.
|
|
197
|
+
// The value is read when the map starts; MapLibre keeps one setting for all maps on the page.
|
|
198
|
+
reduceMotion: prefersReducedMotion(),
|
|
199
|
+
locale: {
|
|
200
|
+
"Map.Title": t.canvasTitle,
|
|
201
|
+
"CooperativeGesturesHandler.WindowsHelpText": t.gestureWindows,
|
|
202
|
+
"CooperativeGesturesHandler.MacHelpText": t.gestureMac,
|
|
203
|
+
"CooperativeGesturesHandler.MobileHelpText": t.gestureMobile
|
|
204
|
+
}
|
|
205
|
+
}, fail);
|
|
206
|
+
map = instance;
|
|
207
|
+
instance.on("error", event => {
|
|
208
|
+
// A missing paid resource must remain visible and recoverable, including failures after initial load.
|
|
209
|
+
if ("sourceId" in event || "tile" in event || state() === "loading" || replacingStyle) fail();
|
|
210
|
+
});
|
|
211
|
+
instance.on("style.load", () => {
|
|
212
|
+
replacingStyle = false;
|
|
213
|
+
});
|
|
214
|
+
instance.on("load", () => {
|
|
215
|
+
if (disposed || attempt !== generation) return;
|
|
216
|
+
setState("ready");
|
|
217
|
+
refit();
|
|
218
|
+
});
|
|
219
|
+
instance.on("movestart", event => {
|
|
220
|
+
if (event.originalEvent) touch();
|
|
221
|
+
});
|
|
222
|
+
instance.on("move", syncOverlay);
|
|
223
|
+
// Pin separation is decided again once a zoom ends, not on every animation frame.
|
|
224
|
+
instance.on("zoomend", () => {
|
|
225
|
+
if (map === instance && touched) setChosenZoom(instance.getZoom());
|
|
226
|
+
});
|
|
227
|
+
instance.on("resize", syncOverlay);
|
|
228
|
+
} catch {
|
|
229
|
+
fail();
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
const clearSelectedPin = () => {
|
|
233
|
+
const marker = selected();
|
|
234
|
+
if (!marker || state() !== "ready" || !map) return;
|
|
235
|
+
const f = frame();
|
|
236
|
+
const lon = marker.point.lon + (f ? worldCopy(map, f) * 360 : 0);
|
|
237
|
+
const p = map.project([lon, marker.point.lat]);
|
|
238
|
+
const offset = f ? pinOffsets(sortMarkers(props.markers ?? []), f, zoomFactor(), props.ownLocation?.point).get(marker.id) : undefined;
|
|
239
|
+
const x = p.x + (offset?.dx ?? 0);
|
|
240
|
+
const y = p.y + (offset?.dy ?? 0);
|
|
241
|
+
const w = root.clientWidth;
|
|
242
|
+
const h = root.clientHeight;
|
|
243
|
+
const tile = info.getBoundingClientRect();
|
|
244
|
+
const bounds = root.getBoundingClientRect();
|
|
245
|
+
const tileTop = tile.top - bounds.top - 8;
|
|
246
|
+
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;
|
|
247
|
+
if (!covered && x >= 16 && x <= w - 16 && y >= 16 && y <= h - 16) return;
|
|
248
|
+
touch();
|
|
249
|
+
// Put the drawn pin, offset included, in the free band above the tile.
|
|
250
|
+
const targetX = w / 2;
|
|
251
|
+
const targetY = tile.height > 0 ? tileTop / 2 : h / 2;
|
|
252
|
+
const target = map.unproject([x + w / 2 - targetX, y + h / 2 - targetY]);
|
|
253
|
+
const camera = {
|
|
254
|
+
center: [target.lng, target.lat]
|
|
255
|
+
};
|
|
256
|
+
if (prefersReducedMotion()) map.jumpTo(camera);else map.easeTo(camera);
|
|
257
|
+
};
|
|
258
|
+
onMount(() => {
|
|
259
|
+
mounted = true;
|
|
260
|
+
const theme = () => setDark(!!root.closest('.dark, .k2b-dark, [data-theme="dark"]'));
|
|
261
|
+
theme();
|
|
262
|
+
for (let ancestor = root; ancestor; ancestor = ancestor.parentElement) {
|
|
263
|
+
const observer = new MutationObserver(theme);
|
|
264
|
+
observer.observe(ancestor, {
|
|
265
|
+
attributes: true,
|
|
266
|
+
attributeFilter: ["class", "data-theme"]
|
|
267
|
+
});
|
|
268
|
+
themes.push(observer);
|
|
269
|
+
}
|
|
270
|
+
setMeasuredWidth(root.clientWidth);
|
|
271
|
+
resize = new ResizeObserver(() => {
|
|
272
|
+
setMeasuredWidth(root.clientWidth);
|
|
273
|
+
map?.resize();
|
|
274
|
+
refit();
|
|
275
|
+
});
|
|
276
|
+
resize.observe(root);
|
|
277
|
+
infoResize = new ResizeObserver(clearSelectedPin);
|
|
278
|
+
infoResize.observe(info);
|
|
279
|
+
const enter = () => {
|
|
280
|
+
visible = true;
|
|
281
|
+
intersection?.disconnect();
|
|
282
|
+
if (frame()) void start();
|
|
283
|
+
};
|
|
284
|
+
if (!frame()) setState("empty");
|
|
285
|
+
if (typeof IntersectionObserver === "undefined") enter();else {
|
|
286
|
+
intersection = new IntersectionObserver(entries => {
|
|
287
|
+
if (entries.some(entry => entry.isIntersecting)) enter();
|
|
288
|
+
}, {
|
|
289
|
+
threshold: 0,
|
|
290
|
+
rootMargin: "0px"
|
|
291
|
+
});
|
|
292
|
+
intersection.observe(root);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
createEffect(on(frame, value => {
|
|
296
|
+
if (!mounted) return;
|
|
297
|
+
if (!value) {
|
|
298
|
+
removeMap();
|
|
299
|
+
setState("empty");
|
|
300
|
+
} else if (state() === "empty") {
|
|
301
|
+
setState("static");
|
|
302
|
+
if (visible) void start();
|
|
303
|
+
} else refit();
|
|
304
|
+
}, {
|
|
305
|
+
defer: true
|
|
306
|
+
}));
|
|
307
|
+
createEffect(() => {
|
|
308
|
+
const style = resolvedStyle();
|
|
309
|
+
if (state() === "ready" && map && style !== currentStyle) {
|
|
310
|
+
currentStyle = style;
|
|
311
|
+
replacingStyle = true;
|
|
312
|
+
map.setStyle(style);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
createEffect(() => {
|
|
316
|
+
selected();
|
|
317
|
+
state();
|
|
318
|
+
untrack(clearSelectedPin);
|
|
319
|
+
});
|
|
320
|
+
onCleanup(() => {
|
|
321
|
+
disposed = true;
|
|
322
|
+
intersection?.disconnect();
|
|
323
|
+
resize?.disconnect();
|
|
324
|
+
infoResize?.disconnect();
|
|
325
|
+
for (const observer of themes) observer.disconnect();
|
|
326
|
+
removeMap();
|
|
327
|
+
});
|
|
328
|
+
const zoom = direction => {
|
|
329
|
+
if (!map || state() !== "ready") return;
|
|
330
|
+
touch();
|
|
331
|
+
const options = {
|
|
332
|
+
animate: !prefersReducedMotion()
|
|
333
|
+
};
|
|
334
|
+
if (direction === "in") map.zoomIn(options);else map.zoomOut(options);
|
|
335
|
+
};
|
|
336
|
+
return (() => {
|
|
337
|
+
var _el$ = _$getNextElement(_tmpl$6),
|
|
338
|
+
_el$2 = _el$.firstChild,
|
|
339
|
+
_el$3 = _el$2.nextSibling,
|
|
340
|
+
_el$28 = _el$3.nextSibling,
|
|
341
|
+
[_el$29, _co$8] = _$getNextMarker(_el$28.nextSibling),
|
|
342
|
+
_el$4 = _el$29.nextSibling,
|
|
343
|
+
_el$1 = _el$4.firstChild,
|
|
344
|
+
[_el$10, _co$2] = _$getNextMarker(_el$1.nextSibling),
|
|
345
|
+
_el$11 = _el$10.nextSibling,
|
|
346
|
+
[_el$12, _co$3] = _$getNextMarker(_el$11.nextSibling),
|
|
347
|
+
_el$13 = _el$4.nextSibling,
|
|
348
|
+
_el$14 = _el$13.firstChild,
|
|
349
|
+
_el$17 = _el$14.firstChild,
|
|
350
|
+
[_el$18, _co$4] = _$getNextMarker(_el$17.nextSibling),
|
|
351
|
+
_el$19 = _el$18.nextSibling,
|
|
352
|
+
[_el$20, _co$5] = _$getNextMarker(_el$19.nextSibling),
|
|
353
|
+
_el$22 = _el$14.nextSibling,
|
|
354
|
+
[_el$23, _co$6] = _$getNextMarker(_el$22.nextSibling),
|
|
355
|
+
_el$24 = _el$13.nextSibling,
|
|
356
|
+
_el$25 = _el$24.firstChild,
|
|
357
|
+
_el$26 = _el$25.nextSibling,
|
|
358
|
+
[_el$27, _co$7] = _$getNextMarker(_el$26.nextSibling);
|
|
359
|
+
var _ref$ = root;
|
|
360
|
+
typeof _ref$ === "function" ? _$use(_ref$, _el$) : root = _el$;
|
|
361
|
+
_$insert(_el$2, () => messages().summary({
|
|
362
|
+
count: props.markers?.length ?? 0
|
|
363
|
+
}));
|
|
364
|
+
var _ref$2 = live;
|
|
365
|
+
typeof _ref$2 === "function" ? _$use(_ref$2, _el$3) : live = _el$3;
|
|
366
|
+
_$insert(_el$, _$createComponent(Show, {
|
|
367
|
+
get when() {
|
|
368
|
+
return frame();
|
|
369
|
+
},
|
|
370
|
+
get fallback() {
|
|
371
|
+
return (() => {
|
|
372
|
+
var _el$30 = _$getNextElement(_tmpl$8);
|
|
373
|
+
_$insert(_el$30, _$createComponent(Show, {
|
|
374
|
+
get when() {
|
|
375
|
+
return empty();
|
|
376
|
+
},
|
|
377
|
+
get children() {
|
|
378
|
+
var _el$31 = _$getNextElement(_tmpl$7);
|
|
379
|
+
_$insert(_el$31, empty);
|
|
380
|
+
return _el$31;
|
|
381
|
+
}
|
|
382
|
+
}));
|
|
383
|
+
return _el$30;
|
|
384
|
+
})();
|
|
385
|
+
},
|
|
386
|
+
children: value => _$createComponent(MapGeometry, _$mergeProps(props, {
|
|
387
|
+
get frame() {
|
|
388
|
+
return value();
|
|
389
|
+
},
|
|
390
|
+
get boxStyle() {
|
|
391
|
+
return boxStyle();
|
|
392
|
+
},
|
|
393
|
+
get zoomFactor() {
|
|
394
|
+
return zoomFactor();
|
|
395
|
+
},
|
|
396
|
+
get onSelect() {
|
|
397
|
+
return props.onSelect;
|
|
398
|
+
},
|
|
399
|
+
interactive: true
|
|
400
|
+
}))
|
|
401
|
+
}), _el$29, _co$8);
|
|
402
|
+
_$insert(_el$4, _$createComponent(Show, {
|
|
403
|
+
get when() {
|
|
404
|
+
return notice();
|
|
405
|
+
},
|
|
406
|
+
get children() {
|
|
407
|
+
var _el$5 = _$getNextElement(_tmpl$);
|
|
408
|
+
_$insert(_el$5, notice);
|
|
409
|
+
return _el$5;
|
|
410
|
+
}
|
|
411
|
+
}), _el$10, _co$2);
|
|
412
|
+
_$insert(_el$4, _$createComponent(Show, {
|
|
413
|
+
get when() {
|
|
414
|
+
return state() === "loading" || state() === "error" || state() === "no-webgl";
|
|
415
|
+
},
|
|
416
|
+
get children() {
|
|
417
|
+
var _el$6 = _$getNextElement(_tmpl$2),
|
|
418
|
+
_el$7 = _el$6.firstChild,
|
|
419
|
+
_el$8 = _el$7.nextSibling,
|
|
420
|
+
_el$9 = _el$8.nextSibling,
|
|
421
|
+
[_el$0, _co$] = _$getNextMarker(_el$9.nextSibling);
|
|
422
|
+
_$insert(_el$8, (() => {
|
|
423
|
+
var _c$ = _$memo(() => state() === "loading");
|
|
424
|
+
return () => _c$() ? messages().loading : _$memo(() => state() === "error")() ? messages().error : messages().noWebgl;
|
|
425
|
+
})());
|
|
426
|
+
_$insert(_el$6, _$createComponent(Show, {
|
|
427
|
+
get when() {
|
|
428
|
+
return state() === "error";
|
|
429
|
+
},
|
|
430
|
+
get children() {
|
|
431
|
+
return _$createComponent(Button, {
|
|
432
|
+
size: "xs",
|
|
433
|
+
variant: "text",
|
|
434
|
+
onClick: () => needsReload() ? window.location.reload() : void start(),
|
|
435
|
+
get children() {
|
|
436
|
+
return _$memo(() => !!needsReload())() ? messages().reload : messages().retry;
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}), _el$0, _co$);
|
|
441
|
+
_$effect(() => _$className(_el$7, state() === "loading" ? "ti ti-loader-2 k2b-spin" : state() === "error" ? "ti ti-alert-circle" : "ti ti-info-circle"));
|
|
442
|
+
return _el$6;
|
|
443
|
+
}
|
|
444
|
+
}), _el$12, _co$3);
|
|
445
|
+
_$insert(_el$14, _$createComponent(IconButton, {
|
|
446
|
+
get label() {
|
|
447
|
+
return messages().zoomIn;
|
|
448
|
+
},
|
|
449
|
+
tooltip: false,
|
|
450
|
+
get disabled() {
|
|
451
|
+
return state() !== "ready";
|
|
452
|
+
},
|
|
453
|
+
onClick: () => zoom("in"),
|
|
454
|
+
get children() {
|
|
455
|
+
return _$getNextElement(_tmpl$3);
|
|
456
|
+
}
|
|
457
|
+
}), _el$18, _co$4);
|
|
458
|
+
_$insert(_el$14, _$createComponent(IconButton, {
|
|
459
|
+
get label() {
|
|
460
|
+
return messages().zoomOut;
|
|
461
|
+
},
|
|
462
|
+
tooltip: false,
|
|
463
|
+
get disabled() {
|
|
464
|
+
return state() !== "ready";
|
|
465
|
+
},
|
|
466
|
+
onClick: () => zoom("out"),
|
|
467
|
+
get children() {
|
|
468
|
+
return _$getNextElement(_tmpl$4);
|
|
469
|
+
}
|
|
470
|
+
}), _el$20, _co$5);
|
|
471
|
+
_$insert(_el$13, _$createComponent(Show, {
|
|
472
|
+
get when() {
|
|
473
|
+
return props.onLocate;
|
|
474
|
+
},
|
|
475
|
+
get children() {
|
|
476
|
+
return _$createComponent(IconButton, {
|
|
477
|
+
"class": "k2b-map-view__locate",
|
|
478
|
+
tooltip: false,
|
|
479
|
+
get label() {
|
|
480
|
+
return messages().locate;
|
|
481
|
+
},
|
|
482
|
+
get ["aria-pressed"]() {
|
|
483
|
+
return !!props.ownLocation;
|
|
484
|
+
},
|
|
485
|
+
onClick: () => props.onLocate?.(),
|
|
486
|
+
get children() {
|
|
487
|
+
return _$getNextElement(_tmpl$5);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}), _el$23, _co$6);
|
|
492
|
+
var _ref$3 = info;
|
|
493
|
+
typeof _ref$3 === "function" ? _$use(_ref$3, _el$25) : info = _el$25;
|
|
494
|
+
_$insert(_el$25, _$createComponent(Show, {
|
|
495
|
+
get when() {
|
|
496
|
+
return selectedId();
|
|
497
|
+
},
|
|
498
|
+
keyed: true,
|
|
499
|
+
children: _id => {
|
|
500
|
+
// Keep the tile's state and focus for this selection while its marker data refreshes.
|
|
501
|
+
const initial = selected();
|
|
502
|
+
const current = () => selected() ?? initial;
|
|
503
|
+
const marker = {
|
|
504
|
+
get id() {
|
|
505
|
+
return current().id;
|
|
506
|
+
},
|
|
507
|
+
get point() {
|
|
508
|
+
return current().point;
|
|
509
|
+
},
|
|
510
|
+
get mark() {
|
|
511
|
+
return current().mark;
|
|
512
|
+
},
|
|
513
|
+
get label() {
|
|
514
|
+
return current().label;
|
|
515
|
+
},
|
|
516
|
+
get tone() {
|
|
517
|
+
return current().tone;
|
|
518
|
+
},
|
|
519
|
+
get selected() {
|
|
520
|
+
return current().selected;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
return props.infoTile?.(marker);
|
|
524
|
+
}
|
|
525
|
+
}));
|
|
526
|
+
_$insert(_el$24, _$createComponent(MapFootRow, {
|
|
527
|
+
get scale() {
|
|
528
|
+
return scale();
|
|
529
|
+
},
|
|
530
|
+
get children() {
|
|
531
|
+
return props.attribution;
|
|
532
|
+
}
|
|
533
|
+
}), _el$27, _co$7);
|
|
534
|
+
_$effect(_p$ => {
|
|
535
|
+
var _v$ = `k2b-map-view${props.class ? ` ${props.class}` : ""}`,
|
|
536
|
+
_v$2 = `${props.height}px`,
|
|
537
|
+
_v$3 = state(),
|
|
538
|
+
_v$4 = messages().mapLabel;
|
|
539
|
+
_v$ !== _p$.e && _$className(_el$, _p$.e = _v$);
|
|
540
|
+
_v$2 !== _p$.t && _$setStyleProperty(_el$, "height", _p$.t = _v$2);
|
|
541
|
+
_v$3 !== _p$.a && _$setAttribute(_el$, "data-state", _p$.a = _v$3);
|
|
542
|
+
_v$4 !== _p$.o && _$setAttribute(_el$, "aria-label", _p$.o = _v$4);
|
|
543
|
+
return _p$;
|
|
544
|
+
}, {
|
|
545
|
+
e: undefined,
|
|
546
|
+
t: undefined,
|
|
547
|
+
a: undefined,
|
|
548
|
+
o: undefined
|
|
549
|
+
});
|
|
550
|
+
return _el$;
|
|
551
|
+
})();
|
|
552
|
+
}
|
|
553
|
+
//# 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 createEffect(() => props.onStateChange?.(state()));\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 {\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 fail,\n );\n map = instance;\n instance.on(\"error\", (event) => {\n // A missing paid resource must remain visible and recoverable, including failures after initial load.\n if (\"sourceId\" in event || \"tile\" in event || 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":[]}
|