import { memo, useMemo } from "react"; import type { GestureSample } from "../../hooks/useGestureRecording"; interface GestureTrailOverlayProps { samples: GestureSample[]; sampleCount?: number; trail?: Array<{ x: number; y: number }>; simplifiedPoints?: Map>; canvasRect: { left: number; top: number; width: number; height: number } | null; compositionSize?: { width: number; height: number }; mode: "recording" | "preview"; accentColor?: string; } export const GestureTrailOverlay = memo(function GestureTrailOverlay({ samples, sampleCount, trail, simplifiedPoints, canvasRect, compositionSize, mode, accentColor = "#3CE6AC", }: GestureTrailOverlayProps) { const trailPoints = useMemo(() => { if (!canvasRect) return ""; if (trail && trail.length > 1) { return trail.map((p) => `${p.x - canvasRect.left},${p.y - canvasRect.top}`).join(" "); } if (samples.length === 0) return ""; return samples .filter((s) => s.properties.x != null && s.properties.y != null) .map((s) => `${s.properties.x},${s.properties.y}`) .join(" "); // eslint-disable-next-line react-hooks/exhaustive-deps }, [samples, trail, sampleCount, canvasRect?.left, canvasRect?.top]); const simplifiedPath = useMemo(() => { if (!simplifiedPoints || simplifiedPoints.size === 0) return ""; const pts: Array<{ x: number; y: number; pct: number }> = []; for (const [pct, props] of simplifiedPoints) { if (props.x != null && props.y != null) { pts.push({ x: props.x, y: props.y, pct }); } } pts.sort((a, b) => a.pct - b.pct); if (pts.length === 0) return ""; return pts.map((p) => `${p.x},${p.y}`).join(" "); }, [simplifiedPoints]); const diamondPositions = useMemo(() => { if (!simplifiedPoints || simplifiedPoints.size === 0) return []; const pts: Array<{ x: number; y: number; pct: number }> = []; for (const [pct, props] of simplifiedPoints) { if (props.x != null && props.y != null) { pts.push({ x: props.x, y: props.y, pct }); } } return pts.sort((a, b) => a.pct - b.pct); }, [simplifiedPoints]); if (!canvasRect || (samples.length < 2 && !simplifiedPoints)) return null; return ( 1 ? `0 0 ${canvasRect.width} ${canvasRect.height}` : `0 0 ${compositionSize?.width ?? canvasRect.width} ${compositionSize?.height ?? canvasRect.height}` } > {mode === "recording" && trailPoints && ( )} {mode === "preview" && ( <> {trailPoints && ( )} {simplifiedPath && ( )} {diamondPositions.map((pt) => ( ))} )} ); });