Spaces:
Paused
Paused
File size: 3,285 Bytes
55153d0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import { motion } from 'framer-motion'
import { Globe } from 'lucide-react'
import { mockNodes, mockConnections } from '../data/mockData.js'
export default function ActivityMap() {
const nodeMap = Object.fromEntries(mockNodes.map(n => [n.name, n]))
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4, delay: 0.3 }}
className="glass rounded-2xl p-4"
>
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<Globe className="w-4 h-4 text-primary" />
<span className="text-sm font-semibold">Global Activity</span>
</div>
<span className="text-[10px] text-secondary font-mono">{mockNodes.length} nodes</span>
</div>
<div className="relative aspect-[2/1] rounded-xl bg-bg/50 overflow-hidden grid-bg">
{/* Connection lines */}
<svg className="absolute inset-0 w-full h-full">
{mockConnections.map((conn, i) => {
const from = nodeMap[conn.from]
const to = nodeMap[conn.to]
if (!from || !to) return null
return (
<g key={i}>
<line
x1={`${from.x}%`} y1={`${from.y}%`}
x2={`${to.x}%`} y2={`${to.y}%`}
stroke="rgba(255,138,0,0.15)"
strokeWidth="1"
/>
<motion.circle
r="2"
fill="#FF8A00"
initial={{ offsetDistance: '0%' }}
animate={{ offsetDistance: ['0%', '100%'] }}
transition={{ duration: 2 + i * 0.3, repeat: Infinity, ease: 'linear' }}
style={{
offsetPath: `path('M ${from.x * 4} ${from.y * 2} L ${to.x * 4} ${to.y * 2}')`,
offsetRotate: '0deg',
}}
/>
</g>
)
})}
</svg>
{/* Nodes */}
{mockNodes.map((node, i) => (
<div
key={node.name}
className="absolute group"
style={{ left: `${node.x}%`, top: `${node.y}%`, transform: 'translate(-50%, -50%)' }}
>
<motion.div
className="w-2 h-2 rounded-full bg-primary"
animate={{ scale: [1, 1.5, 1], opacity: [0.6, 1, 0.6] }}
transition={{ duration: 2, delay: i * 0.2, repeat: Infinity }}
/>
<motion.div
className="absolute inset-0 rounded-full border border-primary/40"
animate={{ scale: [1, 3, 1], opacity: [0.5, 0, 0.5] }}
transition={{ duration: 2, delay: i * 0.2, repeat: Infinity }}
/>
<div className="absolute left-3 top-1/2 -translate-y-1/2 whitespace-nowrap text-[9px] text-secondary opacity-0 group-hover:opacity-100 transition-opacity">
{node.name} · {node.latency}ms
</div>
</div>
))}
</div>
<div className="mt-2 flex items-center justify-between text-[10px] text-secondary">
<span>Every pulse = active transfer</span>
<span className="text-success">All nodes online</span>
</div>
</motion.div>
)
}
|