SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
2.1 KB · 41 lines tsx
Raw Blame History
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