'use client' import React, { useEffect, useState, useRef } from 'react' import { motion, AnimatePresence } from 'motion/react' interface GhostCursorProps { isActive: boolean containerRef: React.RefObject targetId?: string | null } export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorProps) { const [position, setPosition] = useState({ x: 0, y: 0 }) const [visible, setVisible] = useState(false) const intervalRef = useRef(null) useEffect(() => { if (!isActive) { setVisible(false) if (intervalRef.current) clearInterval(intervalRef.current) return } const container = containerRef.current if (!container) return setVisible(true) // Initialisation sécurisée const initialRect = container.getBoundingClientRect() const initialCx = initialRect.width > 0 ? initialRect.width / 2 : window.innerWidth / 2 const initialCy = initialRect.height > 0 ? initialRect.height / 2 : window.innerHeight / 2 setPosition({ x: initialCx + (Math.random() - 0.5) * 200, y: initialCy + (Math.random() - 0.5) * 200, }) let angle = Math.random() * Math.PI * 2 let targetX = initialCx + Math.cos(angle) * 250 let targetY = initialCy + Math.sin(angle) * 250 intervalRef.current = setInterval(() => { // Recalculer les dimensions à chaque tick pour s'adapter aux redimensionnements const currentContainer = containerRef.current if (!currentContainer) return const containerRect = currentContainer.getBoundingClientRect() const cx = containerRect.width / 2 const cy = containerRect.height / 2 let currentTargetX = targetX; let currentTargetY = targetY; if (targetId) { const nodeElement = document.querySelector(`[data-id="${targetId}"]`); if (nodeElement) { const nodeRect = nodeElement.getBoundingClientRect(); currentTargetX = nodeRect.left - containerRect.left + nodeRect.width / 2; currentTargetY = nodeRect.top - containerRect.top + nodeRect.height / 2; } } setPosition(prev => { const dx = currentTargetX - prev.x const dy = currentTargetY - prev.y const dist = Math.sqrt(dx * dx + dy * dy) if (!targetId && dist < 20) { angle = Math.random() * Math.PI * 2 const radius = 150 + Math.random() * 200 targetX = cx + Math.cos(angle) * radius targetY = cy + Math.sin(angle) * radius } const speed = targetId ? 0.15 : 0.06; let newX = prev.x + dx * speed; let newY = prev.y + dy * speed; // Protection Anti-NaN qui bloquait le curseur en haut à gauche if (isNaN(newX)) newX = cx; if (isNaN(newY)) newY = cy; return { x: newX, y: newY, } }) }, 50) return () => { if (intervalRef.current) clearInterval(intervalRef.current) } }, [isActive, containerRef, targetId]) return ( {visible && (
AI ✦
)}
) }