spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1import { geoEqualEarth, type GeoPermissibleObjects } from 'd3-geo';2import { t } from '@/i18n';3import { cn } from '@/lib/cn';4import { MAP_HEIGHT, MAP_WIDTH, worldPaths } from '@/lib/map-geo';56/**7 * Small static locator map for a country hero: the world in a muted tone, the country (and its neighbours,8 * lighter) in the accent, plus a ring at the capital / centroid so micro-states stay visible. Server component.9 */10export function MiniMap({ iso3, neighbours = [], latitude, longitude, name, className }: { iso3: string; neighbours?: string[]; latitude?: number | null; longitude?: number | null; name: string; className?: string }) {11 const { paths, sphere } = worldPaths();12 const projection = geoEqualEarth().fitExtent(13 [14 [4, 4],15 [MAP_WIDTH - 4, MAP_HEIGHT - 4],16 ],17 { type: 'Sphere' } as GeoPermissibleObjects,18 );19 const pt = latitude != null && longitude != null ? projection([longitude, latitude]) : null;20 const nb = new Set(neighbours);21 const own = paths.find((p) => p.iso3 === iso3);22 return (23 <svg viewBox={`0 0 ${MAP_WIDTH} ${MAP_HEIGHT}`} className={cn('h-auto w-full', className)} role="img" aria-label={t('country.miniMap', { name })}>24 <title>{t('country.miniMap', { name })}</title>25 <path d={sphere} fill="var(--map-water)" stroke="var(--rule)" strokeWidth={1} />26 <g stroke="var(--map-stroke)" strokeWidth={0.5} strokeLinejoin="round">27 {paths.map((p, i) => (28 <path key={p.iso3 ?? `${p.name}-${i}`} d={p.d} fill={p.iso3 === iso3 ? 'var(--accent)' : p.iso3 && nb.has(p.iso3) ? 'var(--accent-soft)' : 'var(--nodata)'} fillOpacity={p.iso3 === iso3 ? 1 : p.iso3 && nb.has(p.iso3) ? 1 : 0.7} />29 ))}30 {own ? <path d={own.d} fill="none" stroke="var(--ink)" strokeWidth={0.8} /> : null}31 </g>32 {pt ? (33 <g>34 <circle cx={pt[0]} cy={pt[1]} r={14} fill="none" stroke="var(--accent)" strokeWidth={2.5} opacity={0.9} />35 <circle cx={pt[0]} cy={pt[1]} r={4} fill="var(--accent)" stroke="var(--surface)" strokeWidth={1.5} />36 </g>37 ) : null}38 </svg>39 );40}41