efficient-shell 4.134.0 → 4.137.1
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/LICENSE +6 -17
- package/README.md +84 -8
- package/dist/Browser-ZX5OTOKK.js +43 -0
- package/dist/Calculator-4SQGOQFQ.js +29 -0
- package/dist/ConfirmDialog-NPKW2XHM.js +1 -0
- package/dist/CurrencyConverter-2KOM7L6V.js +21 -0
- package/dist/Documents-IZTIQYPG.js +52 -0
- package/dist/Files-B63KKXGZ.js +89 -0
- package/dist/Notepad-WA77V45J.js +25 -0
- package/dist/PdfViewer-RBRGEKWF.js +1 -0
- package/dist/PomodoroTimer-SDUBKXUS.js +99 -0
- package/dist/Preview-D4KOA4OI.js +187 -0
- package/dist/Sidebar-Y57LYXXI.js +23 -0
- package/dist/Spreadsheet-JX5E6WH6.js +37 -0
- package/dist/Stock-XAQ5WMUZ.js +16 -0
- package/dist/Weather-HLAGJ5LV.js +60 -0
- package/dist/WorldClock-IRI4VCTA.js +32 -0
- package/dist/apps/index.js +1 -151
- package/dist/brand.css +1 -1
- package/dist/chunk-3A46NCXK.js +29 -0
- package/dist/chunk-44UO7FYU.js +11 -0
- package/dist/chunk-466CM2TJ.js +1 -0
- package/dist/chunk-57MIENLJ.js +1 -0
- package/dist/chunk-5CRAF2AD.js +2 -0
- package/dist/chunk-A2OQLLYK.js +6 -0
- package/dist/chunk-B43AGQET.js +4 -0
- package/dist/chunk-BR22X7E5.js +1 -0
- package/dist/chunk-BUTSU7FO.js +1 -0
- package/dist/chunk-D65T4H6J.js +1 -0
- package/dist/chunk-ESL5TDNA.js +1 -0
- package/dist/chunk-FBDZGO3V.js +1 -0
- package/dist/chunk-FHTLC7HH.js +1 -0
- package/dist/chunk-FQLMX3IE.js +948 -0
- package/dist/chunk-H562R4GX.js +34 -0
- package/dist/chunk-JN4WXTWJ.js +106 -0
- package/dist/chunk-LVDRBRYU.js +1 -0
- package/dist/chunk-LWLCNQY7.js +1 -0
- package/dist/chunk-MAIHBBWT.js +1 -0
- package/dist/chunk-NPJH5MD7.js +13 -0
- package/dist/chunk-OCSOMMY2.js +1 -0
- package/dist/chunk-OQDWLHZI.js +1 -0
- package/dist/chunk-OWSAMA3I.js +23 -0
- package/dist/chunk-PH3PRIFP.js +5 -0
- package/dist/chunk-TAWKWSPN.js +9 -0
- package/dist/chunk-U4GTZPXP.js +1 -0
- package/dist/chunk-UB4JIOLD.js +2 -0
- package/dist/chunk-UZAJ5BF6.js +9 -0
- package/dist/chunk-VEGMDXT4.js +1 -0
- package/dist/chunk-VTVSMRFX.js +1 -0
- package/dist/chunk-VVAGSKW7.js +1 -0
- package/dist/chunk-XO43FJRM.js +19 -0
- package/dist/chunk-Y7BOLDRM.js +69 -0
- package/dist/file-intake/index.js +1 -4
- package/dist/{index-DZ7E7bCl.d.ts → index-DVI9DMSu.d.ts} +189 -18
- package/dist/index.d.ts +2 -2
- package/dist/index.js +639 -7473
- package/dist/map/index.js +20 -540
- package/dist/markdown/index.js +6 -184
- package/dist/markup/index.js +1 -135
- package/dist/page-tabs/index.js +21 -709
- package/dist/sounds-OMHXVVQ4.js +1 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -19
- package/dist/ui.css +78 -10
- package/package.json +4 -3
- package/dist/Browser-O3QZGUF2.js +0 -482
- package/dist/Browser-O3QZGUF2.js.map +0 -1
- package/dist/Calculator-L6N5X3KU.js +0 -192
- package/dist/Calculator-L6N5X3KU.js.map +0 -1
- package/dist/ConfirmDialog-LYSSZSUD.js +0 -4
- package/dist/ConfirmDialog-LYSSZSUD.js.map +0 -1
- package/dist/CurrencyConverter-64MKXB3D.js +0 -236
- package/dist/CurrencyConverter-64MKXB3D.js.map +0 -1
- package/dist/Documents-5WXXYCLI.js +0 -441
- package/dist/Documents-5WXXYCLI.js.map +0 -1
- package/dist/Files-AUURUUDN.js +0 -805
- package/dist/Files-AUURUUDN.js.map +0 -1
- package/dist/Notepad-GPXJVPB7.js +0 -410
- package/dist/Notepad-GPXJVPB7.js.map +0 -1
- package/dist/PdfViewer-HKO6P4SR.js +0 -5
- package/dist/PdfViewer-HKO6P4SR.js.map +0 -1
- package/dist/PomodoroTimer-4TQBWLP2.js +0 -633
- package/dist/PomodoroTimer-4TQBWLP2.js.map +0 -1
- package/dist/Preview-FOZYPKM2.js +0 -2959
- package/dist/Preview-FOZYPKM2.js.map +0 -1
- package/dist/Sidebar-BPU7RCZP.js +0 -291
- package/dist/Sidebar-BPU7RCZP.js.map +0 -1
- package/dist/Spreadsheet-3C66BBBF.js +0 -519
- package/dist/Spreadsheet-3C66BBBF.js.map +0 -1
- package/dist/Stock-IF4IHYLU.js +0 -158
- package/dist/Stock-IF4IHYLU.js.map +0 -1
- package/dist/Weather-725PFR7T.js +0 -431
- package/dist/Weather-725PFR7T.js.map +0 -1
- package/dist/WorldClock-UU4NZIQ7.js +0 -202
- package/dist/WorldClock-UU4NZIQ7.js.map +0 -1
- package/dist/apps/index.js.map +0 -1
- package/dist/chunk-2TPTHAKI.js +0 -316
- package/dist/chunk-2TPTHAKI.js.map +0 -1
- package/dist/chunk-4P44JXDS.js +0 -195
- package/dist/chunk-4P44JXDS.js.map +0 -1
- package/dist/chunk-5O42JXQE.js +0 -26
- package/dist/chunk-5O42JXQE.js.map +0 -1
- package/dist/chunk-72CQWN7O.js +0 -547
- package/dist/chunk-72CQWN7O.js.map +0 -1
- package/dist/chunk-7CCHEEYC.js +0 -94
- package/dist/chunk-7CCHEEYC.js.map +0 -1
- package/dist/chunk-BE7FZOFU.js +0 -17
- package/dist/chunk-BE7FZOFU.js.map +0 -1
- package/dist/chunk-D276EMXS.js +0 -57
- package/dist/chunk-D276EMXS.js.map +0 -1
- package/dist/chunk-D7PYW2QS.js +0 -265
- package/dist/chunk-D7PYW2QS.js.map +0 -1
- package/dist/chunk-DVZWYWSD.js +0 -26
- package/dist/chunk-DVZWYWSD.js.map +0 -1
- package/dist/chunk-ET6ID4LP.js +0 -102
- package/dist/chunk-ET6ID4LP.js.map +0 -1
- package/dist/chunk-GA35NEND.js +0 -56
- package/dist/chunk-GA35NEND.js.map +0 -1
- package/dist/chunk-GIGV2ZRW.js +0 -70
- package/dist/chunk-GIGV2ZRW.js.map +0 -1
- package/dist/chunk-IPXN646P.js +0 -14
- package/dist/chunk-IPXN646P.js.map +0 -1
- package/dist/chunk-IRWSRJ4K.js +0 -48
- package/dist/chunk-IRWSRJ4K.js.map +0 -1
- package/dist/chunk-IULP5BCD.js +0 -79
- package/dist/chunk-IULP5BCD.js.map +0 -1
- package/dist/chunk-MGGY74RY.js +0 -14
- package/dist/chunk-MGGY74RY.js.map +0 -1
- package/dist/chunk-OLJDJYSU.js +0 -13678
- package/dist/chunk-OLJDJYSU.js.map +0 -1
- package/dist/chunk-PIGDNN5F.js +0 -46
- package/dist/chunk-PIGDNN5F.js.map +0 -1
- package/dist/chunk-Q2MJVSJT.js +0 -7
- package/dist/chunk-Q2MJVSJT.js.map +0 -1
- package/dist/chunk-Q3LT745N.js +0 -3710
- package/dist/chunk-Q3LT745N.js.map +0 -1
- package/dist/chunk-QAGQRNKI.js +0 -145
- package/dist/chunk-QAGQRNKI.js.map +0 -1
- package/dist/chunk-QRL64J5F.js +0 -503
- package/dist/chunk-QRL64J5F.js.map +0 -1
- package/dist/chunk-QSKCQUZE.js +0 -1103
- package/dist/chunk-QSKCQUZE.js.map +0 -1
- package/dist/chunk-R4OQIQYX.js +0 -153
- package/dist/chunk-R4OQIQYX.js.map +0 -1
- package/dist/chunk-RT6DSB5Y.js +0 -143
- package/dist/chunk-RT6DSB5Y.js.map +0 -1
- package/dist/chunk-SHQM5CK3.js +0 -549
- package/dist/chunk-SHQM5CK3.js.map +0 -1
- package/dist/chunk-T4VQHMG4.js +0 -822
- package/dist/chunk-T4VQHMG4.js.map +0 -1
- package/dist/chunk-TRCWINHF.js +0 -105
- package/dist/chunk-TRCWINHF.js.map +0 -1
- package/dist/chunk-TW7LPMVR.js +0 -16
- package/dist/chunk-TW7LPMVR.js.map +0 -1
- package/dist/chunk-W622KQTD.js +0 -465
- package/dist/chunk-W622KQTD.js.map +0 -1
- package/dist/chunk-X4Q6G253.js +0 -416
- package/dist/chunk-X4Q6G253.js.map +0 -1
- package/dist/chunk-YNKK7NE3.js +0 -171
- package/dist/chunk-YNKK7NE3.js.map +0 -1
- package/dist/chunk-YPO6RDMX.js +0 -20
- package/dist/chunk-YPO6RDMX.js.map +0 -1
- package/dist/file-intake/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/map/index.js.map +0 -1
- package/dist/markdown/index.js.map +0 -1
- package/dist/markup/index.js.map +0 -1
- package/dist/page-tabs/index.js.map +0 -1
- package/dist/sounds-NT4DEZGD.js +0 -3
- package/dist/sounds-NT4DEZGD.js.map +0 -1
- package/dist/ui/index.js.map +0 -1
package/dist/map/index.js
CHANGED
|
@@ -1,541 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
23
|
-
watcher.observe(control, { attributes: true, attributeFilter: ["class"] });
|
|
24
|
-
return () => watcher.disconnect();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// src/map/maplibre.ts
|
|
28
|
-
var MAPLIBRE_WORKER_FILE = "maplibre-gl-worker.mjs";
|
|
29
|
-
var mapLibreWorkerUrl = (version) => `/maplibre-gl/${version}/${MAPLIBRE_WORKER_FILE}`;
|
|
30
|
-
var loading = null;
|
|
31
|
-
function loadMapLibre() {
|
|
32
|
-
loading ??= Promise.all([import('maplibre-gl'), import('maplibre-gl/dist/maplibre-gl.css')]).then(([maplibre]) => {
|
|
33
|
-
maplibre.setWorkerUrl(mapLibreWorkerUrl(maplibre.getVersion()));
|
|
34
|
-
return maplibre;
|
|
35
|
-
}).catch((error) => {
|
|
36
|
-
loading = null;
|
|
37
|
-
throw error;
|
|
38
|
-
});
|
|
39
|
-
return loading;
|
|
40
|
-
}
|
|
41
|
-
function subscribe(onChange) {
|
|
42
|
-
const watcher = new MutationObserver(onChange);
|
|
43
|
-
watcher.observe(document.documentElement, { attributes: true, attributeFilter: ROOT_THEME_ATTRIBUTES });
|
|
44
|
-
return () => watcher.disconnect();
|
|
45
|
-
}
|
|
46
|
-
var isDark = rootIsDark;
|
|
47
|
-
function useDarkTheme() {
|
|
48
|
-
return useSyncExternalStore(subscribe, isDark, () => false);
|
|
49
|
-
}
|
|
50
|
-
var ROUTE_SOURCE = "routes";
|
|
51
|
-
function accentColor() {
|
|
52
|
-
const probe = document.createElement("span");
|
|
53
|
-
probe.className = "text-blue-600";
|
|
54
|
-
probe.style.display = "none";
|
|
55
|
-
document.body.appendChild(probe);
|
|
56
|
-
const color = getComputedStyle(probe).color || "#2563eb";
|
|
57
|
-
probe.remove();
|
|
58
|
-
return toRgb(color);
|
|
59
|
-
}
|
|
60
|
-
function toRgb(css) {
|
|
61
|
-
const ctx = document.createElement("canvas").getContext("2d");
|
|
62
|
-
if (!ctx) return "#2563eb";
|
|
63
|
-
ctx.fillStyle = "#2563eb";
|
|
64
|
-
ctx.fillStyle = css;
|
|
65
|
-
ctx.fillRect(0, 0, 1, 1);
|
|
66
|
-
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
|
|
67
|
-
return `rgb(${r}, ${g}, ${b})`;
|
|
68
|
-
}
|
|
69
|
-
var STYLES = {
|
|
70
|
-
light: "https://tiles.openfreemap.org/styles/positron",
|
|
71
|
-
dark: "https://tiles.openfreemap.org/styles/dark"
|
|
72
|
-
};
|
|
73
|
-
var WORLD = { center: [30, 20], zoom: 1 };
|
|
74
|
-
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
75
|
-
function iconElement(paths, selected) {
|
|
76
|
-
const svg = document.createElementNS(SVG_NS, "svg");
|
|
77
|
-
svg.setAttribute("viewBox", "0 0 24 24");
|
|
78
|
-
svg.setAttribute("fill", "none");
|
|
79
|
-
svg.setAttribute("stroke", "currentColor");
|
|
80
|
-
svg.setAttribute("stroke-width", "2");
|
|
81
|
-
svg.setAttribute("aria-hidden", "true");
|
|
82
|
-
svg.setAttribute("class", selected ? "h-4 w-4" : "h-3.5 w-3.5");
|
|
83
|
-
for (const d of paths) {
|
|
84
|
-
const path = document.createElementNS(SVG_NS, "path");
|
|
85
|
-
path.setAttribute("stroke-linecap", "round");
|
|
86
|
-
path.setAttribute("stroke-linejoin", "round");
|
|
87
|
-
path.setAttribute("d", d);
|
|
88
|
-
svg.appendChild(path);
|
|
89
|
-
}
|
|
90
|
-
return svg;
|
|
91
|
-
}
|
|
92
|
-
function pinElement(pin, selected) {
|
|
93
|
-
const el = document.createElement("button");
|
|
94
|
-
el.type = "button";
|
|
95
|
-
el.title = pin.approximate ? `${pin.label} (approximate)` : pin.label;
|
|
96
|
-
el.setAttribute("aria-label", pin.approximate ? `${pin.label}, approximate location` : pin.label);
|
|
97
|
-
el.dataset.pin = pin.key;
|
|
98
|
-
el.className = [
|
|
99
|
-
"relative grid place-items-center rounded-full border-2 border-white font-semibold leading-none shadow-md cursor-pointer",
|
|
100
|
-
pin.tone,
|
|
101
|
-
selected ? "h-8 w-8 text-xs ring-2 ring-gray-900 ring-offset-1" : "h-6 w-6 text-[10px]",
|
|
102
|
-
pin.approximate ? "border-dashed opacity-80" : "",
|
|
103
|
-
pin.faded && !selected ? "opacity-40" : ""
|
|
104
|
-
].join(" ");
|
|
105
|
-
if (pin.icon?.length) el.appendChild(iconElement(pin.icon, selected));
|
|
106
|
-
else el.textContent = pin.glyph;
|
|
107
|
-
if (pin.badge) {
|
|
108
|
-
const badge = document.createElement("span");
|
|
109
|
-
badge.setAttribute("aria-hidden", "true");
|
|
110
|
-
badge.className = [
|
|
111
|
-
"absolute -right-2 -top-2 grid h-4 min-w-4 place-items-center rounded-full px-0.5 text-[9px] font-semibold leading-none shadow",
|
|
112
|
-
pin.badgeTone ?? "bg-white text-gray-900"
|
|
113
|
-
].join(" ");
|
|
114
|
-
badge.textContent = pin.badge;
|
|
115
|
-
el.appendChild(badge);
|
|
116
|
-
}
|
|
117
|
-
return el;
|
|
118
|
-
}
|
|
119
|
-
function EntityMap({
|
|
120
|
-
pins,
|
|
121
|
-
selectedKey,
|
|
122
|
-
focus,
|
|
123
|
-
onSelect,
|
|
124
|
-
ariaLabel,
|
|
125
|
-
className = "",
|
|
126
|
-
children,
|
|
127
|
-
routes,
|
|
128
|
-
fitTo,
|
|
129
|
-
attribution
|
|
130
|
-
}) {
|
|
131
|
-
const box = useRef(null);
|
|
132
|
-
const map = useRef(null);
|
|
133
|
-
const lib = useRef(null);
|
|
134
|
-
const markers = useRef([]);
|
|
135
|
-
const fitted = useRef("");
|
|
136
|
-
const [ready, setReady] = useState(false);
|
|
137
|
-
const [failed, setFailed] = useState(false);
|
|
138
|
-
const theme = useDarkTheme() ? "dark" : "light";
|
|
139
|
-
const latest = useRef({ onSelect, pins, selectedKey });
|
|
140
|
-
useEffect(() => {
|
|
141
|
-
latest.current = { onSelect, pins, selectedKey };
|
|
142
|
-
});
|
|
143
|
-
const revealSelected = useCallback(() => {
|
|
144
|
-
const m = map.current;
|
|
145
|
-
const { pins: shown, selectedKey: chosen } = latest.current;
|
|
146
|
-
const pin = chosen ? shown.find((p) => p.key === chosen) : void 0;
|
|
147
|
-
if (!m || !pin || m.getBounds().contains([pin.lng, pin.lat])) return;
|
|
148
|
-
const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
149
|
-
m.easeTo({ center: [pin.lng, pin.lat], duration: reduced ? 0 : 400 });
|
|
150
|
-
}, []);
|
|
151
|
-
useEffect(() => {
|
|
152
|
-
let cancelled = false;
|
|
153
|
-
let created = null;
|
|
154
|
-
let observer = null;
|
|
155
|
-
let unfoldWatch = () => {
|
|
156
|
-
};
|
|
157
|
-
void (async () => {
|
|
158
|
-
try {
|
|
159
|
-
const maplibre = await loadMapLibre();
|
|
160
|
-
if (cancelled || !box.current) return;
|
|
161
|
-
lib.current = maplibre;
|
|
162
|
-
created = new maplibre.Map({
|
|
163
|
-
container: box.current,
|
|
164
|
-
style: STYLES[theme],
|
|
165
|
-
center: WORLD.center,
|
|
166
|
-
zoom: WORLD.zoom,
|
|
167
|
-
attributionControl: attribution ? { compact: true, customAttribution: attribution } : { compact: true },
|
|
168
|
-
dragRotate: false,
|
|
169
|
-
pitchWithRotate: false,
|
|
170
|
-
touchPitch: false,
|
|
171
|
-
maxPitch: 0
|
|
172
|
-
});
|
|
173
|
-
created.touchZoomRotate.disableRotation();
|
|
174
|
-
created.keyboard.disableRotation();
|
|
175
|
-
created.addControl(new maplibre.NavigationControl({ showCompass: false }), "top-right");
|
|
176
|
-
created.on("error", (event) => console.warn("[map]", event.error?.message));
|
|
177
|
-
unfoldWatch = foldAttributionOnce(box.current.querySelector(".maplibregl-ctrl-attrib"));
|
|
178
|
-
const current = created;
|
|
179
|
-
observer = new ResizeObserver(() => {
|
|
180
|
-
current.resize();
|
|
181
|
-
revealSelected();
|
|
182
|
-
});
|
|
183
|
-
observer.observe(box.current);
|
|
184
|
-
map.current = created;
|
|
185
|
-
setReady(true);
|
|
186
|
-
} catch (error) {
|
|
187
|
-
console.error("[map] could not start", error);
|
|
188
|
-
if (!cancelled) setFailed(true);
|
|
189
|
-
}
|
|
190
|
-
})();
|
|
191
|
-
return () => {
|
|
192
|
-
cancelled = true;
|
|
193
|
-
observer?.disconnect();
|
|
194
|
-
unfoldWatch();
|
|
195
|
-
markers.current.forEach((m) => m.remove());
|
|
196
|
-
markers.current = [];
|
|
197
|
-
created?.remove();
|
|
198
|
-
map.current = null;
|
|
199
|
-
};
|
|
200
|
-
}, []);
|
|
201
|
-
const shownTheme = useRef(theme);
|
|
202
|
-
useEffect(() => {
|
|
203
|
-
if (!ready || !map.current || shownTheme.current === theme) return;
|
|
204
|
-
shownTheme.current = theme;
|
|
205
|
-
map.current.setStyle(STYLES[theme]);
|
|
206
|
-
}, [ready, theme]);
|
|
207
|
-
useEffect(() => {
|
|
208
|
-
const m = map.current;
|
|
209
|
-
const maplibre = lib.current;
|
|
210
|
-
if (!ready || !m || !maplibre) return;
|
|
211
|
-
markers.current.forEach((marker) => marker.remove());
|
|
212
|
-
markers.current = [];
|
|
213
|
-
const ordered = [...pins].sort((a, b) => Number(a.key === selectedKey) - Number(b.key === selectedKey));
|
|
214
|
-
for (const pin of ordered) {
|
|
215
|
-
const el = pinElement(pin, pin.key === selectedKey);
|
|
216
|
-
el.addEventListener("click", (event) => {
|
|
217
|
-
event.stopPropagation();
|
|
218
|
-
latest.current.onSelect(pin.key);
|
|
219
|
-
});
|
|
220
|
-
markers.current.push(new maplibre.Marker({ element: el, anchor: "center" }).setLngLat([pin.lng, pin.lat]).addTo(m));
|
|
221
|
-
}
|
|
222
|
-
}, [ready, pins, selectedKey]);
|
|
223
|
-
useEffect(() => {
|
|
224
|
-
if (!ready || !selectedKey) return;
|
|
225
|
-
const frame = requestAnimationFrame(revealSelected);
|
|
226
|
-
return () => cancelAnimationFrame(frame);
|
|
227
|
-
}, [ready, selectedKey, revealSelected]);
|
|
228
|
-
useEffect(() => {
|
|
229
|
-
const m = map.current;
|
|
230
|
-
const maplibre = lib.current;
|
|
231
|
-
const target = fitTo ? pins.filter((p) => fitTo.includes(p.key)) : pins;
|
|
232
|
-
if (!ready || !m || !maplibre || target.length === 0) return;
|
|
233
|
-
const key = target.map((p) => `${p.key}@${p.lat},${p.lng}`).sort().join("|");
|
|
234
|
-
if (fitted.current === key) return;
|
|
235
|
-
const first = fitted.current === "";
|
|
236
|
-
fitted.current = key;
|
|
237
|
-
if (target.length === 1) {
|
|
238
|
-
m.jumpTo({ center: [target[0].lng, target[0].lat], zoom: 13 });
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
const bounds = new maplibre.LngLatBounds([target[0].lng, target[0].lat], [target[0].lng, target[0].lat]);
|
|
242
|
-
for (const p of target) bounds.extend([p.lng, p.lat]);
|
|
243
|
-
m.fitBounds(bounds, { padding: 48, maxZoom: 14, animate: !first });
|
|
244
|
-
}, [ready, pins, fitTo]);
|
|
245
|
-
useEffect(() => {
|
|
246
|
-
const m = map.current;
|
|
247
|
-
if (!ready || !m) return;
|
|
248
|
-
const data = {
|
|
249
|
-
type: "FeatureCollection",
|
|
250
|
-
features: (routes ?? []).filter((r) => r.coordinates.length >= 2).map((r) => ({
|
|
251
|
-
type: "Feature",
|
|
252
|
-
properties: { key: r.key, estimate: r.estimate, faded: !!r.faded },
|
|
253
|
-
geometry: { type: "LineString", coordinates: r.coordinates }
|
|
254
|
-
}))
|
|
255
|
-
};
|
|
256
|
-
const draw = () => {
|
|
257
|
-
const color = accentColor();
|
|
258
|
-
const opacity = ["case", ["get", "faded"], 0.25, 0.85];
|
|
259
|
-
const source = m.getSource(ROUTE_SOURCE);
|
|
260
|
-
if (source) source.setData(data);
|
|
261
|
-
else m.addSource(ROUTE_SOURCE, { type: "geojson", data });
|
|
262
|
-
if (m.getLayer("routes-road")) m.setPaintProperty("routes-road", "line-color", color);
|
|
263
|
-
else m.addLayer({
|
|
264
|
-
id: "routes-road",
|
|
265
|
-
type: "line",
|
|
266
|
-
source: ROUTE_SOURCE,
|
|
267
|
-
filter: ["!", ["get", "estimate"]],
|
|
268
|
-
layout: { "line-join": "round", "line-cap": "round" },
|
|
269
|
-
paint: { "line-color": color, "line-width": 4, "line-opacity": opacity }
|
|
270
|
-
});
|
|
271
|
-
if (m.getLayer("routes-estimate")) m.setPaintProperty("routes-estimate", "line-color", color);
|
|
272
|
-
else m.addLayer({
|
|
273
|
-
id: "routes-estimate",
|
|
274
|
-
type: "line",
|
|
275
|
-
source: ROUTE_SOURCE,
|
|
276
|
-
filter: ["get", "estimate"],
|
|
277
|
-
layout: { "line-join": "round", "line-cap": "round" },
|
|
278
|
-
paint: { "line-color": color, "line-width": 3, "line-dasharray": [1.5, 1.5], "line-opacity": opacity }
|
|
279
|
-
});
|
|
280
|
-
};
|
|
281
|
-
const tryDraw = () => {
|
|
282
|
-
try {
|
|
283
|
-
draw();
|
|
284
|
-
} catch (error) {
|
|
285
|
-
console.debug("[map] routes wait for the style", error);
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
tryDraw();
|
|
289
|
-
m.on("style.load", tryDraw);
|
|
290
|
-
m.once("idle", tryDraw);
|
|
291
|
-
return () => {
|
|
292
|
-
m.off("style.load", tryDraw);
|
|
293
|
-
m.off("idle", tryDraw);
|
|
294
|
-
};
|
|
295
|
-
}, [ready, routes, theme]);
|
|
296
|
-
useEffect(() => {
|
|
297
|
-
const m = map.current;
|
|
298
|
-
if (!ready || !m || !focus) return;
|
|
299
|
-
const pin = pins.find((p) => p.key === focus.key);
|
|
300
|
-
if (!pin) return;
|
|
301
|
-
const to = { center: [pin.lng, pin.lat], zoom: Math.max(m.getZoom(), 13) };
|
|
302
|
-
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) m.jumpTo(to);
|
|
303
|
-
else m.flyTo({ ...to, duration: 600 });
|
|
304
|
-
}, [ready, focus?.n]);
|
|
305
|
-
return /* @__PURE__ */ jsxs("div", { className: `relative min-h-72 overflow-hidden rounded-lg border border-gray-200 bg-gray-100 ${className}`, children: [
|
|
306
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx("div", { ref: box, className: "h-full w-full", role: "region", "aria-label": ariaLabel }) }),
|
|
307
|
-
failed && /* @__PURE__ */ jsx("p", { className: "absolute inset-0 grid place-items-center p-6 text-center text-sm text-gray-500", children: "The map could not be drawn here. The list has everything it shows." }),
|
|
308
|
-
children
|
|
309
|
-
] });
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// src/map/points.ts
|
|
313
|
-
var PENDING_POLL_MS = 3e3;
|
|
314
|
-
var mapPointsRefetchInterval = (data) => data?.pending ? PENDING_POLL_MS : false;
|
|
315
|
-
var pointKey = (p) => `${p.kind}:${p.id}`;
|
|
316
|
-
var isOnMap = (p) => (p.placement === "located" || p.placement === "approximate") && p.lat != null && p.lng != null;
|
|
317
|
-
function placementNote(placement) {
|
|
318
|
-
switch (placement) {
|
|
319
|
-
case "located":
|
|
320
|
-
return null;
|
|
321
|
-
case "approximate":
|
|
322
|
-
return "Approximate: only the suburb or postcode matched";
|
|
323
|
-
case "pending":
|
|
324
|
-
return "Locating\u2026";
|
|
325
|
-
case "not_found":
|
|
326
|
-
return "Not on the map: address not found";
|
|
327
|
-
case "failed":
|
|
328
|
-
return "Not on the map: the map service could not be reached";
|
|
329
|
-
case "no_address":
|
|
330
|
-
return "Not on the map: no city or postcode";
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
var MAP_CATEGORIES = {
|
|
334
|
-
importer: { label: "Importer", tone: "bg-sky-600 text-white" },
|
|
335
|
-
dealer: { label: "Dealer", tone: "bg-purple-600 text-white" },
|
|
336
|
-
retail: { label: "Retail", tone: "bg-green-600 text-white" },
|
|
337
|
-
supplier: { label: "Supplier", tone: "bg-sky-600 text-white" },
|
|
338
|
-
delivery_location: { label: "Delivery location", tone: "bg-amber-600 text-white" },
|
|
339
|
-
warehouse: { label: "Warehouse", tone: "bg-amber-600 text-white" }
|
|
340
|
-
};
|
|
341
|
-
var DEFAULT_TONE = "bg-gray-700 text-white";
|
|
342
|
-
var CATEGORY_ORDER = ["importer", "dealer", "retail", "supplier", "delivery_location", "warehouse"];
|
|
343
|
-
function pinCategory(p) {
|
|
344
|
-
if (p.kind === "supplier") return "supplier";
|
|
345
|
-
if (p.kind === "customer") return p.category || "importer";
|
|
346
|
-
return p.kind;
|
|
347
|
-
}
|
|
348
|
-
var categoryTone = (category, categories = MAP_CATEGORIES) => categories[category]?.tone ?? DEFAULT_TONE;
|
|
349
|
-
var categoryLabel = (category, categories = MAP_CATEGORIES) => categories[category]?.label ?? category;
|
|
350
|
-
var pinTone = (p, categories) => categoryTone(pinCategory(p), categories);
|
|
351
|
-
function pinGlyph(p, number, categories = MAP_CATEGORIES) {
|
|
352
|
-
if (number != null) return String(number);
|
|
353
|
-
return (categories[pinCategory(p)]?.label ?? "").charAt(0).toUpperCase();
|
|
354
|
-
}
|
|
355
|
-
var SECONDARY_KINDS = ["delivery_location", "warehouse"];
|
|
356
|
-
function locationNumbers(points, kinds = SECONDARY_KINDS) {
|
|
357
|
-
const numbers = /* @__PURE__ */ new Map();
|
|
358
|
-
let n = 0;
|
|
359
|
-
for (const p of points) {
|
|
360
|
-
if (kinds.includes(p.kind)) numbers.set(pointKey(p), ++n);
|
|
361
|
-
}
|
|
362
|
-
return numbers;
|
|
363
|
-
}
|
|
364
|
-
function summarize(points) {
|
|
365
|
-
const summary = { onMap: 0, approximate: 0, pending: 0, off: 0 };
|
|
366
|
-
for (const p of points) {
|
|
367
|
-
if (isOnMap(p)) {
|
|
368
|
-
summary.onMap += 1;
|
|
369
|
-
if (p.placement === "approximate") summary.approximate += 1;
|
|
370
|
-
} else if (p.placement === "pending") summary.pending += 1;
|
|
371
|
-
else summary.off += 1;
|
|
372
|
-
}
|
|
373
|
-
return summary;
|
|
374
|
-
}
|
|
375
|
-
function summaryText(s) {
|
|
376
|
-
const parts = [`${s.onMap} on the map`];
|
|
377
|
-
if (s.approximate) parts.push(`${s.approximate} approximate`);
|
|
378
|
-
if (s.pending) parts.push(`${s.pending} locating`);
|
|
379
|
-
if (s.off) parts.push(`${s.off} not on the map`);
|
|
380
|
-
return parts.join(" \xB7 ");
|
|
381
|
-
}
|
|
382
|
-
function legendCategories(points) {
|
|
383
|
-
const present = [...new Set(points.filter(isOnMap).map(pinCategory))];
|
|
384
|
-
const known = CATEGORY_ORDER.filter((c) => present.includes(c));
|
|
385
|
-
return [...known, ...present.filter((c) => !CATEGORY_ORDER.includes(c))];
|
|
386
|
-
}
|
|
387
|
-
function offMapNotes(points, numbers) {
|
|
388
|
-
return points.filter((p) => !isOnMap(p) && p.placement !== "pending").map((p) => {
|
|
389
|
-
const n = numbers?.get(pointKey(p));
|
|
390
|
-
const note = placementNote(p.placement)?.replace(/^Not on the map: /, "") ?? "";
|
|
391
|
-
return { key: pointKey(p), text: `${n != null ? `${n}. ` : ""}${p.label}: ${note}` };
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
function MapLegend({ categories, palette = MAP_CATEGORIES, floating = true }) {
|
|
395
|
-
if (categories.length < 2) return null;
|
|
396
|
-
return /* @__PURE__ */ jsx("div", { className: `${floating ? "absolute left-3 top-3 z-10 " : ""}flex flex-wrap gap-x-3 gap-y-1 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-xs text-gray-600 shadow-sm`, children: categories.map((c) => /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
397
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: `h-2.5 w-2.5 rounded-full ${categoryTone(c, palette)}` }),
|
|
398
|
-
categoryLabel(c, palette)
|
|
399
|
-
] }, c)) });
|
|
400
|
-
}
|
|
401
|
-
function SelectedCard({ point, number, onOpen, onClose, palette = MAP_CATEGORIES }) {
|
|
402
|
-
const note = placementNote(point.placement);
|
|
403
|
-
const category = pinCategory(point);
|
|
404
|
-
return /* @__PURE__ */ jsxs(
|
|
405
|
-
"section",
|
|
406
|
-
{
|
|
407
|
-
"aria-label": `${point.label}, chosen on the map`,
|
|
408
|
-
className: "absolute bottom-3 left-3 right-3 z-10 max-w-md space-y-1.5 rounded-lg border border-gray-200 bg-white p-3 shadow-md",
|
|
409
|
-
children: [
|
|
410
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
411
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
412
|
-
/* @__PURE__ */ jsxs("h3", { className: "text-sm font-semibold text-gray-900 [overflow-wrap:anywhere]", children: [
|
|
413
|
-
number != null && /* @__PURE__ */ jsxs("span", { className: "mr-1 text-gray-400", children: [
|
|
414
|
-
number,
|
|
415
|
-
"."
|
|
416
|
-
] }),
|
|
417
|
-
point.label,
|
|
418
|
-
point.code && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs font-normal text-gray-400", children: point.code })
|
|
419
|
-
] }),
|
|
420
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: palette[category] ? categoryLabel(category, palette) : point.category })
|
|
421
|
-
] }),
|
|
422
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: onClose, "aria-label": "Close", className: "rounded p-0.5 text-gray-400 hover:text-gray-600", children: /* @__PURE__ */ jsx("svg", { "aria-hidden": true, className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) })
|
|
423
|
-
] }),
|
|
424
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-700 [overflow-wrap:anywhere]", children: point.address || "\u2014" }),
|
|
425
|
-
note && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: note }),
|
|
426
|
-
point.matched && point.placement === "approximate" && /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-400 [overflow-wrap:anywhere]", children: [
|
|
427
|
-
"Placed at: ",
|
|
428
|
-
point.matched
|
|
429
|
-
] }),
|
|
430
|
-
onOpen && /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button_default, { variant: "secondary", size: "sm", onClick: onOpen, children: "Open" }) })
|
|
431
|
-
]
|
|
432
|
-
}
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
function useMapPoints(queryKey, queryFn, { staleTime } = {}) {
|
|
436
|
-
return useQuery({
|
|
437
|
-
queryKey,
|
|
438
|
-
queryFn,
|
|
439
|
-
staleTime,
|
|
440
|
-
refetchInterval: (query) => mapPointsRefetchInterval(query.state.data)
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
var NOTES_SHOWN = 3;
|
|
444
|
-
function LocationsMap({
|
|
445
|
-
queryKey,
|
|
446
|
-
queryFn,
|
|
447
|
-
refreshSignal,
|
|
448
|
-
onOpen,
|
|
449
|
-
ariaLabel,
|
|
450
|
-
title = "Locations",
|
|
451
|
-
palette = MAP_CATEGORIES,
|
|
452
|
-
numbers: givenNumbers,
|
|
453
|
-
className = "",
|
|
454
|
-
mapClassName = "min-h-[240px] flex-1"
|
|
455
|
-
}) {
|
|
456
|
-
const { data, isError, refetch } = useMapPoints(queryKey, queryFn, { staleTime: 0 });
|
|
457
|
-
const mounted = useRef(false);
|
|
458
|
-
useEffect(() => {
|
|
459
|
-
if (!mounted.current) {
|
|
460
|
-
mounted.current = true;
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
void refetch();
|
|
464
|
-
}, [refreshSignal]);
|
|
465
|
-
const [selectedKey, setSelectedKey] = useState(null);
|
|
466
|
-
const points = useMemo(() => data?.points ?? [], [data]);
|
|
467
|
-
const numbers = useMemo(() => givenNumbers ?? locationNumbers(points), [givenNumbers, points]);
|
|
468
|
-
const pins = useMemo(() => points.filter(isOnMap).map((p) => ({
|
|
469
|
-
key: pointKey(p),
|
|
470
|
-
label: p.label,
|
|
471
|
-
lat: p.lat,
|
|
472
|
-
lng: p.lng,
|
|
473
|
-
glyph: pinGlyph(p, numbers.get(pointKey(p)) ?? null, palette),
|
|
474
|
-
tone: pinTone(p, palette),
|
|
475
|
-
approximate: p.placement === "approximate"
|
|
476
|
-
})), [points, numbers, palette]);
|
|
477
|
-
const notes = useMemo(() => offMapNotes(points, numbers), [points, numbers]);
|
|
478
|
-
const legend = useMemo(() => legendCategories(points), [points]);
|
|
479
|
-
const pending = data?.pending ?? 0;
|
|
480
|
-
const selected = points.find((p) => pointKey(p) === selectedKey) ?? null;
|
|
481
|
-
const open = selected && onOpen ? onOpen(selected) : null;
|
|
482
|
-
return /* @__PURE__ */ jsxs("section", { "aria-label": title, className: `flex min-w-0 flex-col ${className}`, children: [
|
|
483
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-h-[30px] items-center justify-between mb-2", children: [
|
|
484
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900", children: title }),
|
|
485
|
-
data && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500", children: summaryText(summarize(points)) })
|
|
486
|
-
] }),
|
|
487
|
-
/* @__PURE__ */ jsxs(
|
|
488
|
-
EntityMap,
|
|
489
|
-
{
|
|
490
|
-
pins,
|
|
491
|
-
selectedKey,
|
|
492
|
-
focus: null,
|
|
493
|
-
onSelect: setSelectedKey,
|
|
494
|
-
ariaLabel,
|
|
495
|
-
className: mapClassName,
|
|
496
|
-
children: [
|
|
497
|
-
/* @__PURE__ */ jsxs("div", { className: "absolute left-3 top-3 z-10 flex max-w-[70%] flex-col items-start gap-1.5", children: [
|
|
498
|
-
/* @__PURE__ */ jsx(MapLegend, { categories: legend, palette, floating: false }),
|
|
499
|
-
isError && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-xs text-gray-600 shadow-sm", children: [
|
|
500
|
-
"Couldn\u2019t load the locations.",
|
|
501
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => void refetch(), className: "font-medium text-blue-600 hover:text-blue-800 hover:underline", children: "Try again" })
|
|
502
|
-
] }),
|
|
503
|
-
!isError && (pending > 0 || notes.length > 0) && /* @__PURE__ */ jsxs("div", { className: "max-w-full space-y-0.5 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-xs shadow-sm", "aria-live": "polite", children: [
|
|
504
|
-
pending > 0 && /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1.5 text-gray-500", children: [
|
|
505
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-3 w-3 animate-spin", fill: "none", viewBox: "0 0 24 24", children: [
|
|
506
|
-
/* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
507
|
-
/* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
|
|
508
|
-
] }),
|
|
509
|
-
"Locating ",
|
|
510
|
-
pending,
|
|
511
|
-
" address",
|
|
512
|
-
pending === 1 ? "" : "es",
|
|
513
|
-
"\u2026"
|
|
514
|
-
] }),
|
|
515
|
-
notes.slice(0, NOTES_SHOWN).map((n) => /* @__PURE__ */ jsx("p", { className: "truncate text-amber-700", title: n.text, children: n.text }, n.key)),
|
|
516
|
-
notes.length > NOTES_SHOWN && /* @__PURE__ */ jsxs("p", { className: "text-gray-500", children: [
|
|
517
|
-
"+",
|
|
518
|
-
notes.length - NOTES_SHOWN,
|
|
519
|
-
" more not on the map"
|
|
520
|
-
] })
|
|
521
|
-
] })
|
|
522
|
-
] }),
|
|
523
|
-
selected && /* @__PURE__ */ jsx(
|
|
524
|
-
SelectedCard,
|
|
525
|
-
{
|
|
526
|
-
point: selected,
|
|
527
|
-
number: numbers.get(pointKey(selected)) ?? null,
|
|
528
|
-
onOpen: open,
|
|
529
|
-
onClose: () => setSelectedKey(null),
|
|
530
|
-
palette
|
|
531
|
-
}
|
|
532
|
-
)
|
|
533
|
-
]
|
|
534
|
-
}
|
|
535
|
-
)
|
|
536
|
-
] });
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
export { COMPACT_SHOW, EntityMap, LocationsMap, MAPLIBRE_WORKER_FILE, MAP_CATEGORIES, MapLegend, PENDING_POLL_MS, SECONDARY_KINDS, SelectedCard, categoryLabel, categoryTone, foldAttributionOnce, isOnMap, legendCategories, loadMapLibre, locationNumbers, mapLibreWorkerUrl, mapPointsRefetchInterval, offMapNotes, pinCategory, pinGlyph, pinTone, placementNote, pointKey, summarize, summaryText, useMapPoints };
|
|
540
|
-
//# sourceMappingURL=index.js.map
|
|
541
|
-
//# sourceMappingURL=index.js.map
|
|
2
|
+
import{Button_default as e}from"../chunk-PH3PRIFP.js";import{rootIsDark as t,ROOT_THEME_ATTRIBUTES as r}from"../chunk-MAIHBBWT.js";import{useRef as n,useState as a,useEffect as o,useCallback as l,useMemo as i,useSyncExternalStore as s}from"react";import{jsxs as c,jsx as d}from"react/jsx-runtime";import{useQuery as u}from"@tanstack/react-query";var p="maplibregl-compact-show";function m(e){if(!e)return()=>{};const t=()=>!!e.classList.contains(p)&&(e.classList.remove(p),!0);if(t())return()=>{};const r=new MutationObserver(()=>{t()&&r.disconnect()});return r.observe(e,{attributes:!0,attributeFilter:["class"]}),()=>r.disconnect()}var h="maplibre-gl-worker.mjs",g=e=>`/maplibre-gl/${e}/${h}`,f=null;function b(){return f??=Promise.all([import("maplibre-gl"),import("maplibre-gl/dist/maplibre-gl.css")]).then(([e])=>(e.setWorkerUrl(g(e.getVersion())),e)).catch(e=>{throw f=null,e}),f}function y(e){const t=new MutationObserver(e);return t.observe(document.documentElement,{attributes:!0,attributeFilter:r}),()=>t.disconnect()}var x=t;var w="routes";function v(){const e=document.createElement("span");e.className="text-blue-600",e.style.display="none",document.body.appendChild(e);const t=getComputedStyle(e).color||"#2563eb";return e.remove(),function(e){const t=document.createElement("canvas").getContext("2d");if(!t)return"#2563eb";t.fillStyle="#2563eb",t.fillStyle=e,t.fillRect(0,0,1,1);const[r,n,a]=t.getImageData(0,0,1,1).data;return`rgb(${r}, ${n}, ${a})`}(t)}var N={light:"https://tiles.openfreemap.org/styles/positron",dark:"https://tiles.openfreemap.org/styles/dark"},k={center:[30,20],zoom:1},C="http://www.w3.org/2000/svg";function $(e,t){const r=document.createElement("button");if(r.type="button",r.title=e.approximate?`${e.label} (approximate)`:e.label,r.setAttribute("aria-label",e.approximate?`${e.label}, approximate location`:e.label),r.dataset.pin=e.key,r.className=["relative grid place-items-center rounded-full border-2 border-white font-semibold leading-none shadow-md cursor-pointer",e.tone,t?"h-8 w-8 text-xs ring-2 ring-gray-900 ring-offset-1":"h-6 w-6 text-[10px]",e.approximate?"border-dashed opacity-80":"",e.faded&&!t?"opacity-40":""].join(" "),e.icon?.length?r.appendChild(function(e,t){const r=document.createElementNS(C,"svg");r.setAttribute("viewBox","0 0 24 24"),r.setAttribute("fill","none"),r.setAttribute("stroke","currentColor"),r.setAttribute("stroke-width","2"),r.setAttribute("aria-hidden","true"),r.setAttribute("class",t?"h-4 w-4":"h-3.5 w-3.5");for(const t of e){const e=document.createElementNS(C,"path");e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.setAttribute("d",t),r.appendChild(e)}return r}(e.icon,t)):r.textContent=e.glyph,e.badge){const t=document.createElement("span");t.setAttribute("aria-hidden","true"),t.className=["absolute -right-2 -top-2 grid h-4 min-w-4 place-items-center rounded-full px-0.5 text-[9px] font-semibold leading-none shadow",e.badgeTone??"bg-white text-gray-900"].join(" "),t.textContent=e.badge,r.appendChild(t)}return r}function L({pins:e,selectedKey:t,focus:r,onSelect:i,ariaLabel:u,className:p="",children:h,routes:g,fitTo:f,attribution:C}){const L=n(null),S=n(null),j=n(null),A=n([]),M=n(""),[T,z]=a(!1),[P,E]=a(!1),F=s(y,x,()=>!1)?"dark":"light",R=n({onSelect:i,pins:e,selectedKey:t});o(()=>{R.current={onSelect:i,pins:e,selectedKey:t}});const B=l(()=>{const e=S.current,{pins:t,selectedKey:r}=R.current,n=r?t.find(e=>e.key===r):void 0;if(!e||!n||e.getBounds().contains([n.lng,n.lat]))return;const a=window.matchMedia("(prefers-reduced-motion: reduce)").matches;e.easeTo({center:[n.lng,n.lat],duration:a?0:400})},[]);o(()=>{let e=!1,t=null,r=null,n=()=>{};return(async()=>{try{const a=await b();if(e||!L.current)return;j.current=a,t=new a.Map({container:L.current,style:N[F],center:k.center,zoom:k.zoom,attributionControl:C?{compact:!0,customAttribution:C}:{compact:!0},dragRotate:!1,pitchWithRotate:!1,touchPitch:!1,maxPitch:0}),t.touchZoomRotate.disableRotation(),t.keyboard.disableRotation(),t.addControl(new a.NavigationControl({showCompass:!1}),"top-right"),t.on("error",e=>console.warn("[map]",e.error?.message)),n=m(L.current.querySelector(".maplibregl-ctrl-attrib"));const o=t;r=new ResizeObserver(()=>{o.resize(),B()}),r.observe(L.current),S.current=t,z(!0)}catch(t){console.error("[map] could not start",t),e||E(!0)}})(),()=>{e=!0,r?.disconnect(),n(),A.current.forEach(e=>e.remove()),A.current=[],t?.remove(),S.current=null}},[]);const q=n(F);return o(()=>{T&&S.current&&q.current!==F&&(q.current=F,S.current.setStyle(N[F]))},[T,F]),o(()=>{const r=S.current,n=j.current;if(!T||!r||!n)return;A.current.forEach(e=>e.remove()),A.current=[];const a=[...e].sort((e,r)=>Number(e.key===t)-Number(r.key===t));for(const e of a){const a=$(e,e.key===t);a.addEventListener("click",t=>{t.stopPropagation(),R.current.onSelect(e.key)}),A.current.push(new n.Marker({element:a,anchor:"center"}).setLngLat([e.lng,e.lat]).addTo(r))}},[T,e,t]),o(()=>{if(!T||!t)return;const e=requestAnimationFrame(B);return()=>cancelAnimationFrame(e)},[T,t,B]),o(()=>{const t=S.current,r=j.current,n=f?e.filter(e=>f.includes(e.key)):e;if(!T||!t||!r||0===n.length)return;const a=n.map(e=>`${e.key}@${e.lat},${e.lng}`).sort().join("|");if(M.current===a)return;const o=""===M.current;if(M.current=a,1===n.length)return void t.jumpTo({center:[n[0].lng,n[0].lat],zoom:13});const l=new r.LngLatBounds([n[0].lng,n[0].lat],[n[0].lng,n[0].lat]);for(const e of n)l.extend([e.lng,e.lat]);t.fitBounds(l,{padding:48,maxZoom:14,animate:!o})},[T,e,f]),o(()=>{const e=S.current;if(!T||!e)return;const t={type:"FeatureCollection",features:(g??[]).filter(e=>e.coordinates.length>=2).map(e=>({type:"Feature",properties:{key:e.key,estimate:e.estimate,faded:!!e.faded},geometry:{type:"LineString",coordinates:e.coordinates}}))},r=()=>{try{(()=>{const r=v(),n=["case",["get","faded"],.25,.85],a=e.getSource(w);a?a.setData(t):e.addSource(w,{type:"geojson",data:t}),e.getLayer("routes-road")?e.setPaintProperty("routes-road","line-color",r):e.addLayer({id:"routes-road",type:"line",source:w,filter:["!",["get","estimate"]],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":r,"line-width":4,"line-opacity":n}}),e.getLayer("routes-estimate")?e.setPaintProperty("routes-estimate","line-color",r):e.addLayer({id:"routes-estimate",type:"line",source:w,filter:["get","estimate"],layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":r,"line-width":3,"line-dasharray":[1.5,1.5],"line-opacity":n}})})()}catch(e){console.debug("[map] routes wait for the style",e)}};return r(),e.on("style.load",r),e.once("idle",r),()=>{e.off("style.load",r),e.off("idle",r)}},[T,g,F]),o(()=>{const t=S.current;if(!T||!t||!r)return;const n=e.find(e=>e.key===r.key);if(!n)return;const a={center:[n.lng,n.lat],zoom:Math.max(t.getZoom(),13)};window.matchMedia("(prefers-reduced-motion: reduce)").matches?t.jumpTo(a):t.flyTo({...a,duration:600})},[T,r?.n]),/* @__PURE__ */c("div",{className:`relative min-h-72 overflow-hidden rounded-lg border border-gray-200 bg-gray-100 ${p}`,children:[
|
|
3
|
+
/* @__PURE__ */d("div",{className:"absolute inset-0",children:/* @__PURE__ */d("div",{ref:L,className:"h-full w-full",role:"region","aria-label":u})}),P&&/* @__PURE__ */d("p",{className:"absolute inset-0 grid place-items-center p-6 text-center text-sm text-gray-500",children:"The map could not be drawn here. The list has everything it shows."}),h]})}var S=3e3,j=e=>!!e?.pending&&3e3,A=e=>`${e.kind}:${e.id}`,M=e=>("located"===e.placement||"approximate"===e.placement)&&null!=e.lat&&null!=e.lng;function T(e){switch(e){case"located":return null;case"approximate":return"Approximate: only the suburb or postcode matched";case"pending":return"Locating…";case"not_found":return"Not on the map: address not found";case"failed":return"Not on the map: the map service could not be reached";case"no_address":return"Not on the map: no city or postcode"}}var z={importer:{label:"Importer",tone:"bg-sky-600 text-white"},dealer:{label:"Dealer",tone:"bg-purple-600 text-white"},retail:{label:"Retail",tone:"bg-green-600 text-white"},supplier:{label:"Supplier",tone:"bg-sky-600 text-white"},delivery_location:{label:"Delivery location",tone:"bg-amber-600 text-white"},warehouse:{label:"Warehouse",tone:"bg-amber-600 text-white"}},P=["importer","dealer","retail","supplier","delivery_location","warehouse"];function E(e){return"supplier"===e.kind?"supplier":"customer"===e.kind?e.category||"importer":e.kind}var F=(e,t=z)=>t[e]?.tone??"bg-gray-700 text-white",R=(e,t=z)=>t[e]?.label??e,B=(e,t)=>F(E(e),t);function q(e,t,r=z){return null!=t?String(t):(r[E(e)]?.label??"").charAt(0).toUpperCase()}var K=["delivery_location","warehouse"];function O(e,t=K){const r=/* @__PURE__ */new Map;let n=0;for(const a of e)t.includes(a.kind)&&r.set(A(a),++n);return r}function W(e){const t={onMap:0,approximate:0,pending:0,off:0};for(const r of e)M(r)?(t.onMap+=1,"approximate"===r.placement&&(t.approximate+=1)):"pending"===r.placement?t.pending+=1:t.off+=1;return t}function I(e){const t=[`${e.onMap} on the map`];return e.approximate&&t.push(`${e.approximate} approximate`),e.pending&&t.push(`${e.pending} locating`),e.off&&t.push(`${e.off} not on the map`),t.join(" · ")}function _(e){const t=[...new Set(e.filter(M).map(E))];return[...P.filter(e=>t.includes(e)),...t.filter(e=>!P.includes(e))]}function D(e,t){return e.filter(e=>!M(e)&&"pending"!==e.placement).map(e=>{const r=t?.get(A(e)),n=T(e.placement)?.replace(/^Not on the map: /,"")??"";return{key:A(e),text:`${null!=r?`${r}. `:""}${e.label}: ${n}`}})}function H({categories:e,palette:t=z,floating:r=!0}){return e.length<2?null:/* @__PURE__ */d("div",{className:(r?"absolute left-3 top-3 z-10 ":"")+"flex flex-wrap gap-x-3 gap-y-1 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-xs text-gray-600 shadow-sm",children:e.map(e=>/* @__PURE__ */c("span",{className:"inline-flex items-center gap-1.5",children:[
|
|
4
|
+
/* @__PURE__ */d("span",{"aria-hidden":!0,className:`h-2.5 w-2.5 rounded-full ${F(e,t)}`}),R(e,t)]},e))})}function Z({point:t,number:r,onOpen:n,onClose:a,palette:o=z}){const l=T(t.placement),i=E(t);/* @__PURE__ */
|
|
5
|
+
return c("section",{"aria-label":`${t.label}, chosen on the map`,className:"absolute bottom-3 left-3 right-3 z-10 max-w-md space-y-1.5 rounded-lg border border-gray-200 bg-white p-3 shadow-md",children:[
|
|
6
|
+
/* @__PURE__ */c("div",{className:"flex items-start justify-between gap-2",children:[
|
|
7
|
+
/* @__PURE__ */c("div",{className:"min-w-0",children:[
|
|
8
|
+
/* @__PURE__ */c("h3",{className:"text-sm font-semibold text-gray-900 [overflow-wrap:anywhere]",children:[null!=r&&/* @__PURE__ */c("span",{className:"mr-1 text-gray-400",children:[r,"."]}),t.label,t.code&&/* @__PURE__ */d("span",{className:"ml-1.5 text-xs font-normal text-gray-400",children:t.code})]}),
|
|
9
|
+
/* @__PURE__ */d("p",{className:"text-xs text-gray-500",children:o[i]?R(i,o):t.category})]}),
|
|
10
|
+
/* @__PURE__ */d("button",{type:"button",onClick:a,"aria-label":"Close",className:"rounded p-0.5 text-gray-400 hover:text-gray-600",children:/* @__PURE__ */d("svg",{"aria-hidden":!0,className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:/* @__PURE__ */d("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12"})})})]}),
|
|
11
|
+
/* @__PURE__ */d("p",{className:"text-sm text-gray-700 [overflow-wrap:anywhere]",children:t.address||"—"}),l&&/* @__PURE__ */d("p",{className:"text-xs text-gray-500",children:l}),t.matched&&"approximate"===t.placement&&/* @__PURE__ */c("p",{className:"text-xs text-gray-400 [overflow-wrap:anywhere]",children:["Placed at: ",t.matched]}),n&&/* @__PURE__ */d("div",{className:"flex justify-end",children:/* @__PURE__ */d(e,{variant:"secondary",size:"sm",onClick:n,children:"Open"})})]})}function U(e,t,{staleTime:r}={}){return u({queryKey:e,queryFn:t,staleTime:r,refetchInterval:e=>j(e.state.data)})}function V({queryKey:e,queryFn:t,refreshSignal:r,onOpen:l,ariaLabel:s,title:u="Locations",palette:p=z,numbers:m,className:h="",mapClassName:g="min-h-[240px] flex-1"}){const{data:f,isError:b,refetch:y}=U(e,t,{staleTime:0}),x=n(!1);o(()=>{x.current?y():x.current=!0},[r]);const[w,v]=a(null),N=i(()=>f?.points??[],[f]),k=i(()=>m??O(N),[m,N]),C=i(()=>N.filter(M).map(e=>({key:A(e),label:e.label,lat:e.lat,lng:e.lng,glyph:q(e,k.get(A(e))??null,p),tone:B(e,p),approximate:"approximate"===e.placement})),[N,k,p]),$=i(()=>D(N,k),[N,k]),S=i(()=>_(N),[N]),j=f?.pending??0,T=N.find(e=>A(e)===w)??null,P=T&&l?l(T):null;/* @__PURE__ */
|
|
12
|
+
return c("section",{"aria-label":u,className:`flex min-w-0 flex-col ${h}`,children:[
|
|
13
|
+
/* @__PURE__ */c("div",{className:"flex min-h-[30px] items-center justify-between mb-2",children:[
|
|
14
|
+
/* @__PURE__ */d("h3",{className:"text-sm font-semibold text-gray-900",children:u}),f&&/* @__PURE__ */d("span",{className:"text-xs text-gray-500",children:I(W(N))})]}),
|
|
15
|
+
/* @__PURE__ */c(L,{pins:C,selectedKey:w,focus:null,onSelect:v,ariaLabel:s,className:g,children:[
|
|
16
|
+
/* @__PURE__ */c("div",{className:"absolute left-3 top-3 z-10 flex max-w-[70%] flex-col items-start gap-1.5",children:[
|
|
17
|
+
/* @__PURE__ */d(H,{categories:S,palette:p,floating:!1}),b&&/* @__PURE__ */c("div",{className:"flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-xs text-gray-600 shadow-sm",children:["Couldn’t load the locations.",
|
|
18
|
+
/* @__PURE__ */d("button",{type:"button",onClick:()=>{y()},className:"font-medium text-blue-600 hover:text-blue-800 hover:underline",children:"Try again"})]}),!b&&(j>0||$.length>0)&&/* @__PURE__ */c("div",{className:"max-w-full space-y-0.5 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-xs shadow-sm","aria-live":"polite",children:[j>0&&/* @__PURE__ */c("p",{className:"flex items-center gap-1.5 text-gray-500",children:[
|
|
19
|
+
/* @__PURE__ */c("svg",{className:"h-3 w-3 animate-spin",fill:"none",viewBox:"0 0 24 24",children:[
|
|
20
|
+
/* @__PURE__ */d("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),
|
|
21
|
+
/* @__PURE__ */d("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"})]}),"Locating ",j," address",1===j?"":"es","…"]}),$.slice(0,3).map(e=>/* @__PURE__ */d("p",{className:"truncate text-amber-700",title:e.text,children:e.text},e.key)),$.length>3&&/* @__PURE__ */c("p",{className:"text-gray-500",children:["+",$.length-3," more not on the map"]})]})]}),T&&/* @__PURE__ */d(Z,{point:T,number:k.get(A(T))??null,onOpen:P,onClose:()=>v(null),palette:p})]})]})}export{p as COMPACT_SHOW,L as EntityMap,V as LocationsMap,h as MAPLIBRE_WORKER_FILE,z as MAP_CATEGORIES,H as MapLegend,S as PENDING_POLL_MS,K as SECONDARY_KINDS,Z as SelectedCard,R as categoryLabel,F as categoryTone,m as foldAttributionOnce,M as isOnMap,_ as legendCategories,b as loadMapLibre,O as locationNumbers,g as mapLibreWorkerUrl,j as mapPointsRefetchInterval,D as offMapNotes,E as pinCategory,q as pinGlyph,B as pinTone,T as placementNote,A as pointKey,W as summarize,I as summaryText,U as useMapPoints};
|