import React from 'react'; import { gsap } from 'gsap'; function FlowingMenu({ items = [], activeItem, onItemClick }) { return (
); } function MenuItem({ link, text, image, isActive, onClick, icon }) { const itemRef = React.useRef(null); const marqueeRef = React.useRef(null); const marqueeInnerRef = React.useRef(null); const animationDefaults = { duration: 0.6, ease: 'expo' }; const findClosestEdge = (mouseX, mouseY, width, height) => { const topEdgeDist = (mouseX - width / 2) ** 2 + mouseY ** 2; const bottomEdgeDist = (mouseX - width / 2) ** 2 + (mouseY - height) ** 2; return topEdgeDist < bottomEdgeDist ? 'top' : 'bottom'; }; const handleMouseEnter = (ev) => { if (!itemRef.current || !marqueeRef.current || !marqueeInnerRef.current) return; const rect = itemRef.current.getBoundingClientRect(); const edge = findClosestEdge( ev.clientX - rect.left, ev.clientY - rect.top, rect.width, rect.height ); gsap.timeline({ defaults: animationDefaults }) .set(marqueeRef.current, { y: edge === 'top' ? '-101%' : '101%' }) .set(marqueeInnerRef.current, { y: edge === 'top' ? '101%' : '-101%' }) .to([marqueeRef.current, marqueeInnerRef.current], { y: '0%' }); }; const handleMouseLeave = (ev) => { if (!itemRef.current || !marqueeRef.current || !marqueeInnerRef.current) return; const rect = itemRef.current.getBoundingClientRect(); const edge = findClosestEdge( ev.clientX - rect.left, ev.clientY - rect.top, rect.width, rect.height ); gsap.timeline({ defaults: animationDefaults }) .to(marqueeRef.current, { y: edge === 'top' ? '-101%' : '101%' }) .to(marqueeInnerRef.current, { y: edge === 'top' ? '101%' : '-101%' }); }; const repeatedMarqueeContent = []; return (
{ e.preventDefault(); onClick(); }} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} > {icon} {text}
{repeatedMarqueeContent}
); } export default FlowingMenu;