All checks were successful
Deploy production / deploy (push) Successful in 1m13s
55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
import type * as Leaflet from 'leaflet';
|
|
import { PUBLIC_MAPTILER_API_KEY } from '$app/env/public';
|
|
|
|
// MapTiler "Dataviz" basemaps on OpenStreetMap data (the site's existing public MapTiler
|
|
// key): dark in the dark theme, light in the light one, swapped live when the theme
|
|
// toggles. Without a key (local dev) it falls back to the standard OSM tiles, darkened
|
|
// with a CSS filter in the dark theme. CARTO's raster tiles need a key since Sept 2026.
|
|
|
|
const isDark = () => document.documentElement.classList.contains('dark');
|
|
|
|
const OSM =
|
|
'© <a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener">OpenStreetMap</a> contributors';
|
|
const MAPTILER =
|
|
'© <a href="https://www.maptiler.com/copyright/" target="_blank" rel="noopener">MapTiler</a>';
|
|
|
|
function source(dark: boolean): { url: string; attribution: string; filtered: boolean } {
|
|
if (PUBLIC_MAPTILER_API_KEY) {
|
|
const style = dark ? 'dataviz-dark' : 'dataviz';
|
|
return {
|
|
url: `https://api.maptiler.com/maps/${style}/256/{z}/{x}/{y}{r}.png?key=${encodeURIComponent(PUBLIC_MAPTILER_API_KEY)}`,
|
|
attribution: `${MAPTILER} ${OSM}`,
|
|
filtered: false
|
|
};
|
|
}
|
|
return {
|
|
url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
|
attribution: OSM,
|
|
filtered: dark
|
|
};
|
|
}
|
|
|
|
/** Adds the themed tile layer to `map`; returns a cleanup for the theme observer. */
|
|
export function addThemedTiles(L: typeof Leaflet, map: Leaflet.Map): () => void {
|
|
const first = source(isDark());
|
|
const layer = L.tileLayer(first.url, {
|
|
maxZoom: 19,
|
|
attribution: first.attribution,
|
|
className: first.filtered ? 'wt-tiles-dim' : ''
|
|
}).addTo(map);
|
|
const apply = () => {
|
|
const s = source(isDark());
|
|
layer.getContainer()?.classList.toggle('wt-tiles-dim', s.filtered);
|
|
layer.setUrl(s.url);
|
|
};
|
|
const observer = new MutationObserver(apply);
|
|
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
|
|
return () => observer.disconnect();
|
|
}
|
|
|
|
/** Leaflet is browser-only: load it on demand (never during SSR). */
|
|
export async function loadLeaflet(): Promise<typeof Leaflet> {
|
|
const mod = await import('leaflet');
|
|
return (mod.default ?? mod) as typeof Leaflet;
|
|
}
|