Central platform for European atproto.<cc> country community websites
Something went wrong. Try again.
2.6 kB · 65 lines
Astro
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566---// The localness device (design system: "one map, framed by country"). It renders in a same-origin// iframe because it needs d3 + topojson at runtime; keeping it out of the main bundle means the// heavy map libs load only when the map scrolls into view (loading="lazy"). All deps are// self-hosted under /public/map/vendor — no third-party runtime requests.//// Build-time values (cc, accent, member dots, and on .eu the active communities) go in the src// query string; the iframe resolves light/dark itself so the map follows the page theme.import { getScope } from '../config/scopes';import { EU27, ALSO_IN_EUROPE } from '../data/europe-regions';
interface Props { /** Member dots as "lon:lat:n,lon:lat:n". Empty renders the country outline with no members yet. */ dots?: string; class?: string; title?: string; /** Internal frame size. Larger + landscape = a denser character grid, for the background use. */ w?: number; h?: number; /** 'cover' fills the frame (no letterbox) for the full-bleed background; default keeps the whole map. */ fit?: 'cover' | 'meet';}
const { dots = '', class: cls, title, w, h, fit } = Astro.props;const scope = getScope(import.meta.env.PUBLIC_SITE_SCOPE);
// Cache-bust: /public map assets are served without a content hash, so browsers keep the old// locality-map.js after a deploy. Bump this when the map renderer changes; it versions both the// iframe URL (fresh HTML) and the script it loads (fresh JS).const MAP_VERSION = '9';
const params = new URLSearchParams({ cc: scope.cc, accent: scope.accent });if (dots) params.set('dots', dots);if (w) params.set('w', String(w));if (h) params.set('h', String(h));if (fit) params.set('fit', fit);params.set('v', MAP_VERSION);// On the aggregate, colour by region — the SAME three tiers as the /stats table (shared lists in// data/europe-regions.ts, so map and stats never disagree): EU members are the bright #, the non-EU// "also in Europe" set (gb/no/ch/is/li) are the dim #, and any other land in the frame is dots.// The renderer reads `active` as the bright set and `lit` as the dim set.if (scope.aggregate) { params.set('active', EU27.join(',')); params.set('lit', ALSO_IN_EUROPE.join(','));}const src = `/map/locality-map.html?${params.toString()}`;---
<iframe class:list={['locality-map', cls]} src={src} title={title ?? 'Where the community is'} loading="lazy" scrolling="no"></iframe>
<style> .locality-map { width: 100%; aspect-ratio: 3 / 2; border: 0; display: block; background: transparent; color-scheme: light dark; }</style>