import React from 'react'; import { ShieldCheck } from 'lucide-react'; import { cn } from '../../shared/utils'; import { Map } from '../map'; import type { LatLng } from '../map/map.types'; export interface EvidenceMapProps extends React.HTMLAttributes { position: LatLng; /** Radius of the capture accuracy circle, in metres. */ accuracyMeters?: number; /** ISO timestamp of the capture. */ capturedAt?: string; /** Integrity digest, e.g. `"sha256:9f3c…"`. */ hash?: string; /** * Always true in practice — the prop exists so the intent is visible at the * call site. The component never renders controls or accepts interaction. * @default true */ readOnly?: boolean; /** @default '220px' */ height?: string; zoom?: number; apiKey?: string; /** @default "Captured at" */ capturedAtLabel?: string; /** @default "Integrity" */ hashLabel?: string; /** @default "Accuracy" */ accuracyLabel?: string; } function formatCoordinate(value: number, positive: string, negative: string): string { return `${Math.abs(value).toFixed(6)}° ${value >= 0 ? positive : negative}`; } /** * Read-only evidence view of a single captured coordinate. * * @description * A preset, not a configurable map: no controls, no dragging, no zooming. The * coordinate is printed in monospace beside an integrity seal, because the * point of this component is that the position belongs to the **record**, not * to the viewer — a map the reader can pan invites the impression that the * location is something they are exploring rather than something that was * captured. * * @ai-rules * 1. Never add controls, drag or zoom to this component. Use `` for anything explorable. * 2. Always pass `capturedAt` and `hash` when the record has them — they are what make the view evidentiary. * 3. Show `accuracyMeters` whenever the capture reported it; a coordinate without its accuracy overstates precision. */ export const EvidenceMap = React.forwardRef( ( { position, accuracyMeters, capturedAt, hash, readOnly = true, height = '220px', zoom = 16, apiKey, capturedAtLabel = 'Captured at', hashLabel = 'Integrity', accuracyLabel = 'Accuracy', className, ...props }, ref ) => (
Coordinates
{formatCoordinate(position.lat, 'N', 'S')} {formatCoordinate(position.lng, 'E', 'W')}
{accuracyMeters !== undefined ? (
{accuracyLabel}
±{Math.round(accuracyMeters)} m
) : null} {capturedAt ? (
{capturedAtLabel}
) : null} {hash ? (
{hash}
) : null}
) ); EvidenceMap.displayName = 'EvidenceMap';