import React, { useState, useEffect } from 'react' interface HeartLogoProps { size?: 'small' | 'medium' | 'large' | 'header' | 'header-no-rays' className?: string onClick?: () => void } export function HeartLogo({ size = 'small', className = '', onClick }: HeartLogoProps) { const [animationOffset, setAnimationOffset] = useState(0) const [isAnimating, setIsAnimating] = useState(false) // Click handler to toggle animation const handleClick = () => { setIsAnimating(!isAnimating) if (onClick) { onClick() } } // Animation for header beams useEffect(() => { if (size !== 'header-no-rays' || !isAnimating) return let animationId: number let startTime = Date.now() const animate = () => { const elapsed = Date.now() - startTime const rotationSpeed = 0.02 // Slow rotation speed const offset = (elapsed * rotationSpeed) % 360 setAnimationOffset(offset) animationId = requestAnimationFrame(animate) } animationId = requestAnimationFrame(animate) return () => { if (animationId) { cancelAnimationFrame(animationId) } } }, [size, isAnimating]) if (size === 'header') { // Header version with rays filling the entire header rectangle return (
{/* Header rays matching loading screen exactly */} {[...Array(16)].map((_, i) => { const angle = (i * 22.5); const rayWidth = 2; // Much thinner rays // Create triangular ray path - thin rays extending to header edges const startAngle = angle - rayWidth; const endAngle = angle + rayWidth; const innerRadius = 0; // Start from center (heart center) const outerRadius = 200; // Extend far beyond to reach all header edges const x1 = Math.cos(startAngle * Math.PI / 180) * innerRadius; const y1 = Math.sin(startAngle * Math.PI / 180) * innerRadius; const x2 = Math.cos(endAngle * Math.PI / 180) * innerRadius; const y2 = Math.sin(endAngle * Math.PI / 180) * innerRadius; const x3 = Math.cos(startAngle * Math.PI / 180) * outerRadius; const y3 = Math.sin(startAngle * Math.PI / 180) * outerRadius; const x4 = Math.cos(endAngle * Math.PI / 180) * outerRadius; const y4 = Math.sin(endAngle * Math.PI / 180) * outerRadius; return ( ); })}
) } if (size === 'header-no-rays') { // Header version with small red beams - compact sunlight effect return (
{/* Red beams extending across entire header rectangle - optimized for wide screens */} {[...Array(32)].map((_, i) => { const angle = (i * 11.25) + animationOffset; // 32 rays, 11.25 degrees apart, animated const rayWidth = 2; // Much narrower rays to show background between them // Create triangular ray path const startAngle = angle - rayWidth; const endAngle = angle + rayWidth; const innerRadius = 0; // Start from heart center // Calculate intersection with rectangle bounds for wide header const getIntersectionWithRect = (angleInDegrees: number) => { const rad = angleInDegrees * Math.PI / 180; const dx = Math.cos(rad); const dy = Math.sin(rad); // Header rectangle bounds (wide format ~3:1 ratio) const rectBoundsX = 200; // Full width const rectBoundsY = 67; // Height to match header proportions // Calculate intersection with each edge let t = Infinity; // Right edge (x = rectBoundsX) if (dx > 0) { t = Math.min(t, rectBoundsX / dx); } // Left edge (x = -rectBoundsX) if (dx < 0) { t = Math.min(t, -rectBoundsX / dx); } // Top edge (y = -rectBoundsY) if (dy < 0) { t = Math.min(t, -rectBoundsY / dy); } // Bottom edge (y = rectBoundsY) if (dy > 0) { t = Math.min(t, rectBoundsY / dy); } return { x: dx * t, y: dy * t }; }; const x1 = Math.cos(startAngle * Math.PI / 180) * innerRadius; const y1 = Math.sin(startAngle * Math.PI / 180) * innerRadius; const x2 = Math.cos(endAngle * Math.PI / 180) * innerRadius; const y2 = Math.sin(endAngle * Math.PI / 180) * innerRadius; const edge1 = getIntersectionWithRect(startAngle); const edge2 = getIntersectionWithRect(endAngle); return ( ); })}
) } // Original square version for other sizes return (
{/* Rising Sun flag style rays - triangular rays extending to rectangle edges */} {[...Array(16)].map((_, i) => { const angle = (i * 22.5); const rayWidth = 11.25; // Half the angle between rays for triangular shape // Create triangular ray path const startAngle = angle - rayWidth; const endAngle = angle + rayWidth; const innerRadius = 0; // Start from center (heart center) // Calculate intersection with rectangle bounds // Rectangle aspect ratio 120:80 = 3:2, so use different bounds for x and y const getIntersectionWithRect = (angleInDegrees: number) => { const rad = angleInDegrees * Math.PI / 180; const dx = Math.cos(rad); const dy = Math.sin(rad); // Rectangle bounds matching the 120x80 aspect ratio (3:2) const rectBoundsX = 100; // Full width const rectBoundsY = 67; // 2/3 of width to maintain 3:2 ratio // Calculate intersection with each edge let t = Infinity; // Right edge (x = rectBoundsX) if (dx > 0) { t = Math.min(t, rectBoundsX / dx); } // Left edge (x = -rectBoundsX) if (dx < 0) { t = Math.min(t, -rectBoundsX / dx); } // Top edge (y = -rectBoundsY) if (dy < 0) { t = Math.min(t, -rectBoundsY / dy); } // Bottom edge (y = rectBoundsY) if (dy > 0) { t = Math.min(t, rectBoundsY / dy); } return { x: dx * t, y: dy * t }; }; const x1 = Math.cos(startAngle * Math.PI / 180) * innerRadius; const y1 = Math.sin(startAngle * Math.PI / 180) * innerRadius; const x2 = Math.cos(endAngle * Math.PI / 180) * innerRadius; const y2 = Math.sin(endAngle * Math.PI / 180) * innerRadius; const edge1 = getIntersectionWithRect(startAngle); const edge2 = getIntersectionWithRect(endAngle); return ( ); })}
) }