{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"data-flow-beam","type":"registry:component","title":"Data Flow Beam","description":"Feixes de luz percorrem os conectores entre prompt, modelo, API, banco, cache e resposta.","author":"UI Catalog <https://ui.codehall.io>","dependencies":["motion"],"registryDependencies":[],"files":[{"path":"components/illustrations/data-flow-beam.tsx","type":"registry:component","content":"'use client'\n\nimport { motion } from 'motion/react'\nimport { Database, FileText, Globe, Server, Sparkles, Zap } from 'lucide-react'\n\n// Ilustração \"Data Flow Beam\": feixes de luz percorrem os conectores entre nós de um pipeline.\n// Herda cores do tema (tokens do shadcn) e anima com motion. Sem props obrigatórias.\nconst NODES = [\n  { id: 'prompt', x: 60, y: 160, label: 'Prompt', Icon: FileText },\n  { id: 'model', x: 280, y: 60, label: 'Modelo', Icon: Sparkles },\n  { id: 'api', x: 280, y: 260, label: 'API', Icon: Globe },\n  { id: 'db', x: 500, y: 110, label: 'Postgres', Icon: Database },\n  { id: 'cache', x: 500, y: 210, label: 'Cache', Icon: Server },\n  { id: 'out', x: 700, y: 160, label: 'Resposta', Icon: Zap },\n] as const\n\nconst EDGES: Array<[string, string, number]> = [\n  ['prompt', 'model', 0],\n  ['prompt', 'api', 0.6],\n  ['model', 'db', 0.3],\n  ['api', 'cache', 0.9],\n  ['db', 'out', 1.2],\n  ['cache', 'out', 1.5],\n]\n\nfunction pathBetween(a: { x: number; y: number }, b: { x: number; y: number }) {\n  const dx = (b.x - a.x) / 2\n  return `M ${a.x + 64} ${a.y} C ${a.x + 64 + dx} ${a.y}, ${b.x - 64 - dx} ${b.y}, ${b.x - 64} ${b.y}`\n}\n\nexport default function DataFlowBeam() {\n  const byId = Object.fromEntries(NODES.map((n) => [n.id, n])) as Record<string, (typeof NODES)[number]>\n  return (\n    <div className=\"relative w-full max-w-3xl text-foreground\">\n      <svg viewBox=\"0 0 760 320\" className=\"h-auto w-full\" role=\"img\" aria-label=\"Fluxo de dados animado entre prompt, modelo, API, banco, cache e resposta\">\n        <defs>\n          <linearGradient id=\"dfb-beam\" x1=\"0\" x2=\"1\" y1=\"0\" y2=\"0\">\n            <stop offset=\"0\" stopColor=\"var(--primary)\" stopOpacity=\"0\" />\n            <stop offset=\"0.5\" stopColor=\"var(--primary)\" />\n            <stop offset=\"1\" stopColor=\"var(--primary)\" stopOpacity=\"0\" />\n          </linearGradient>\n          <filter id=\"dfb-glow\" x=\"-20%\" y=\"-200%\" width=\"140%\" height=\"500%\">\n            <feGaussianBlur stdDeviation=\"2.5\" />\n          </filter>\n        </defs>\n\n        {/* trilhos */}\n        {EDGES.map(([a, b]) => (\n          <path key={`${a}-${b}`} d={pathBetween(byId[a]!, byId[b]!)} fill=\"none\" stroke=\"var(--border)\" strokeWidth=\"1.5\" />\n        ))}\n\n        {/* feixes */}\n        {EDGES.map(([a, b, delay]) => (\n          <g key={`beam-${a}-${b}`}>\n            <motion.path\n              d={pathBetween(byId[a]!, byId[b]!)}\n              fill=\"none\"\n              stroke=\"url(#dfb-beam)\"\n              strokeWidth=\"6\"\n              strokeLinecap=\"round\"\n              filter=\"url(#dfb-glow)\"\n              opacity={0.6}\n              initial={{ pathLength: 0.35, pathSpacing: 1, pathOffset: 0 }}\n              animate={{ pathLength: 0.35, pathSpacing: 1, pathOffset: 1 }}\n              transition={{ duration: 2.4, repeat: Infinity, ease: 'linear', delay }}\n            />\n            <motion.path\n              d={pathBetween(byId[a]!, byId[b]!)}\n              fill=\"none\"\n              stroke=\"url(#dfb-beam)\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              initial={{ pathLength: 0.35, pathSpacing: 1, pathOffset: 0 }}\n              animate={{ pathLength: 0.35, pathSpacing: 1, pathOffset: 1 }}\n              transition={{ duration: 2.4, repeat: Infinity, ease: 'linear', delay }}\n            />\n          </g>\n        ))}\n\n        {/* nós */}\n        {NODES.map((n, i) => (\n          <motion.g\n            key={n.id}\n            initial={{ opacity: 0, scale: 0.9 }}\n            animate={{ opacity: 1, scale: 1 }}\n            transition={{ delay: 0.1 + i * 0.08, duration: 0.5, ease: 'easeOut' }}\n            style={{ transformOrigin: `${n.x}px ${n.y}px` }}\n          >\n            <rect x={n.x - 64} y={n.y - 26} width=\"128\" height=\"52\" rx=\"12\" fill=\"var(--card)\" stroke=\"var(--border)\" />\n            <foreignObject x={n.x - 56} y={n.y - 16} width=\"112\" height=\"32\">\n              <div className=\"flex h-8 items-center gap-2 text-xs font-medium\">\n                <span className=\"flex size-6 items-center justify-center rounded-md bg-muted text-foreground\">\n                  <n.Icon className=\"size-3.5\" />\n                </span>\n                {n.label}\n              </div>\n            </foreignObject>\n          </motion.g>\n        ))}\n      </svg>\n    </div>\n  )\n}\n"}]}