// pathfinding.tsx // Animated SVG illustrating "Automatic pathfinding" // - Central hub + surrounding nodes // - Arrows fade/slide in // - Shortest path highlights on loop // - Respects prefers-reduced-motion 'use client'; import * as React from 'react'; import { motion, useReducedMotion } from 'framer-motion'; import clsx from 'clsx'; type Props = { className?: string; // e.g. "w-full h-64" accent?: string; // main accent color stroke?: string; // neutral stroke color bg?: string; // background color }; const Node = ({ cx, cy, r = 16, fill = "#00b8db", ring = "#E5E7EB", pulse = false, rMotion = 2, }: { cx: number; cy: number; r?: number; fill?: string; ring?: string; pulse?: boolean; rMotion?: number; }) => { const prefersReduced = useReducedMotion(); return ( <> {/* outer ring */} {/* core node */} ); }; const Arrow = ({ d, color = "#111827", delay = 0, }: { d: string; color?: string; delay?: number; }) => ( ); const DashedPath = ({ d, color = "#9CA3AF", dash = 6, delay = 0, loop = false, }: { d: string; color?: string; dash?: number; delay?: number; loop?: boolean; }) => { const prefersReduced = useReducedMotion(); return ( ); }; export default function Pathfinding({ className, accent = "#00b8db", // indigo-800 vibe stroke = "#111827", // gray-900 bg = "#FFFFFF", }: Props) { // Canvas const W = 760; const H = 420; // Layout (simple radial) const center = { x: 380, y: 210 }; const nodes = [ { x: 130, y: 210 }, // left { x: 670, y: 210 }, // right { x: 380, y: 70 }, // top { x: 280, y: 340 }, // bottom-left { x: 500, y: 340 }, // bottom-right ]; // Helper to make arrow path with a small head const arrowTo = (from: { x: number; y: number }, to: { x: number; y: number }) => { const dx = to.x - from.x; const dy = to.y - from.y; const len = Math.hypot(dx, dy); const ux = dx / len; const uy = dy / len; const end = { x: to.x - ux * 18, y: to.y - uy * 18 }; // inset a bit const headL = { x: end.x - uy * 8 - ux * 6, y: end.y + ux * 8 - uy * 6, }; const headR = { x: end.x + uy * 8 - ux * 6, y: end.y - ux * 8 - uy * 6, }; return `M ${from.x} ${from.y} L ${end.x} ${end.y} M ${headL.x} ${headL.y} L ${end.x} ${end.y} L ${headR.x} ${headR.y}`; }; // "Shortest" highlighted route: left -> center -> bottom-right const highlightA = `M ${nodes[0].x} ${nodes[0].y} L ${center.x} ${center.y}`; const highlightB = `M ${center.x} ${center.y} L ${nodes[4].x} ${nodes[4].y}`; // Faint alternative routes const alt1 = `M ${nodes[2].x} ${nodes[2].y} L ${center.x} ${center.y}`; const alt2 = `M ${nodes[3].x} ${nodes[3].y} L ${center.x} ${center.y}`; const alt3 = `M ${center.x} ${center.y} L ${nodes[1].x} ${nodes[1].y}`; return ( ); }