worldwide todo list: global map (List/Map toggle, clustered category pins, Global strip, pick on map, location_precision, tasks.geojson)
All checks were successful
Deploy production / deploy (push) Successful in 1m13s
All checks were successful
Deploy production / deploy (push) Successful in 1m13s
This commit is contained in:
54
src/lib/worldtodo/tiles.ts
Normal file
54
src/lib/worldtodo/tiles.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user