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 (
<div className={`heart-logo ${size} ${className}`}>
<div className="heart-logo-rectangle">
<div className="heart-logo-content">
<div className="heart-logo-rays">
<svg viewBox="0 0 100 100" className="heart-logo-rays-svg" preserveAspectRatio="none">
{/* Header rays matching loading screen exactly */}
<g transform="translate(50, 50)">
{[...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 (
<polygon
key={i}
points={`${x1},${y1} ${x2},${y2} ${x4},${y4} ${x3},${y3}`}
fill={i % 2 === 0 ? "#8B0000" : "#000000"}
opacity="0.9"
/>
);
})}
</g>
</svg>
</div>
<div className="heart-logo-outline">
<svg viewBox="0 0 100 100" className="heart-logo-svg">
<path d="M50,85 C50,85 10,60 10,35 C10,18 20,8 35,8 C42,8 50,13 50,25 C50,13 58,8 65,8 C80,8 90,18 90,35 C90,60 50,85 50,85 Z"
fill="#8B0000"
stroke="#8B0000"
strokeWidth="2"/>
</svg>
</div>
</div>
</div>
</div>
)
}
if (size === 'header-no-rays') {
// Header version with small red beams - compact sunlight effect
return (
<div className={`heart-logo ${size} ${className}`} onClick={handleClick} style={{ cursor: 'pointer' }}>
<div className="heart-logo-content">
<div className="heart-logo-rays">
<svg viewBox="-200 -67 400 134" className="heart-logo-rays-svg" preserveAspectRatio="xMidYMid slice">
{/* Red beams extending across entire header rectangle - optimized for wide screens */}
<g>
{[...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 (
<polygon
key={i}
points={`${x1},${y1} ${x2},${y2} ${edge2.x},${edge2.y} ${edge1.x},${edge1.y}`}
fill={i % 2 === 0 ? "#DC2626" : "#B91C1C"}
opacity="0.6"
/>
);
})}
</g>
</svg>
</div>
<div className="heart-logo-outline">
<svg viewBox="0 0 100 100" className="heart-logo-svg">
<path d="M50,85 C50,85 10,60 10,35 C10,18 20,8 35,8 C42,8 50,13 50,25 C50,13 58,8 65,8 C80,8 90,18 90,35 C90,60 50,85 50,85 Z"
fill="#8B0000"
stroke="#8B0000"
strokeWidth="2"/>
</svg>
</div>
</div>
</div>
)
}
// Original square version for other sizes
return (
<div className={`heart-logo ${size} ${className}`}>
<div className="heart-logo-rectangle">
<div className="heart-logo-content">
<div className="heart-logo-rays">
<svg viewBox="-100 -67 200 134" className="heart-logo-rays-svg">
{/* Rising Sun flag style rays - triangular rays extending to rectangle edges */}
<g>
{[...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 (
<polygon
key={i}
points={`${x1},${y1} ${x2},${y2} ${edge2.x},${edge2.y} ${edge1.x},${edge1.y}`}
fill={i % 2 === 0 ? "#8B0000" : "#000000"}
opacity="0.9"
/>
);
})}
</g>
</svg>
</div>
<div className="heart-logo-outline">
<svg viewBox="0 0 100 100" className="heart-logo-svg">
<path d="M50,85 C50,85 10,60 10,35 C10,18 20,8 35,8 C42,8 50,13 50,25 C50,13 58,8 65,8 C80,8 90,18 90,35 C90,60 50,85 50,85 Z"
fill="#8B0000"
stroke="#8B0000"
strokeWidth="2"/>
</svg>
</div>
</div>
</div>
</div>
)
}