import React from 'react'; import { cn } from '../../shared/utils'; import { mapOverlayPositionClasses } from '../map/map-overlay-position'; import { resolveScale } from '../map/map-scale'; import { useMapTokenColors, withAlpha } from '../map/use-map-token-color'; import type { ColorToken, MapOverlayPosition, MapScale } from '../map/map.types'; /** Glyph used to represent a series in the color key. */ export type MapLegendShape = 'circle' | 'square' | 'line' | 'pin'; export interface MapLegendItem { /** Semantic token, e.g. `'--chart-1'`. Never a hex literal. */ colorToken: ColorToken; label: string; /** @default 'circle' */ shape?: MapLegendShape; /** Fill translucency, matched to the feature being described. @default 0.85 */ fillOpacity?: number; } export interface MapLegendSizeKey { /** Representative values to draw, smallest first. */ values: number[]; /** * The same scale the markers use. `scale.value` is ignored — each entry of * `values` is substituted in turn — but the field is part of `MapScale`, so * pass the marker's scale object straight through. */ scale: MapScale; /** Appended after each value, e.g. `'un.'` or `'km²'`. */ unit?: string; /** Color of the sample discs. @default '--primary' */ colorToken?: ColorToken; /** @default 0.45 */ fillOpacity?: number; } export interface MapLegendProps extends React.HTMLAttributes { /** * `'overlay'` floats over the map and must sit inside a positioned ancestor — * wrap the map and the legend in a `relative` container. `'inline'` flows in * normal layout, for legends placed beside or below the map. * @default 'inline' */ variant?: 'overlay' | 'inline'; /** Anchor for `variant="overlay"`. @default 'bottom-left' */ position?: MapOverlayPosition; /** Color key: one entry per series or choropleth class. */ items?: MapLegendItem[]; /** Size key: what the radius of a proportional symbol means. */ sizeKey?: MapLegendSizeKey; title?: string; /** Accessible name when no `title` is shown. @default "Map legend" */ ariaLabel?: string; } const DEFAULT_ITEM_OPACITY = 0.85; const DEFAULT_SIZE_KEY_OPACITY = 0.45; const DEFAULT_SIZE_KEY_TOKEN: ColorToken = '--primary'; function LegendGlyph({ shape, color }: { shape: MapLegendShape; color: string }) { if (shape === 'line') { return (