Files
open-lovable/components/shared/hero-flame.tsx
T
Developers Digest 13a4c5e1de confirm build
2025-09-10 10:12:06 -04:00

123 lines
3.4 KiB
TypeScript

"use client";
import { useEffect, useRef, useState } from "react";
import { cn } from "@/utils/cn";
// Sample of flame frames - using a subset for performance
const flameFrames = [
`
▄▄▄
▄███▄
▄█████▄
▄███████▄
▄█████████▄
▄███████████▄
▄█████████████▄
▄███████████████▄
█████████████████
███▀▀▀███▀▀▀█████
██ ███ ███
█ ▀ ██
`,
`
▄███▄
▄█████▄
▄███▀███▄
▄████▄████▄
▄███████████▄
▄█████▀▀██████▄
▄██████▄▄███████▄
█████████████████
███▀▀█████▀▀█████
██ ███ ███
█ ▀ ██
`,
`
▄█████▄
▄███████▄
▄█████████▄
▄███▀███▀███▄
▄████▄███▄████▄
▄██████████████▄
████▀▀█████▀▀████
███ ███ ███
██ ▀▀ ███
█ ██
`,
`
▄███████▄
▄█████████▄
▄███████████▄
▄█████▀▀██████▄
▄███████▄▄██████▄
██████████████████
████▀▀▀████▀▀▀████
███ ███ ███
██ ▀▀ ██
█ █
`,
];
interface HeroFlameProps {
className?: string;
size?: "small" | "medium" | "large";
}
export function HeroFlame({ className, size = "medium" }: HeroFlameProps) {
const [frameIndex, setFrameIndex] = useState(0);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
intervalRef.current = setInterval(() => {
setFrameIndex((prev) => (prev + 1) % flameFrames.length);
}, 85);
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, []);
const sizeClasses = {
small: "text-[8px] leading-[10px]",
medium: "text-[12px] leading-[14px]",
large: "text-[16px] leading-[18px]",
};
return (
<div
className={cn("flex gap-4 pointer-events-none select-none", className)}
>
{/* Left flame */}
<div className="relative overflow-hidden">
<pre
className={cn(
"text-heat-100 font-mono whitespace-pre",
sizeClasses[size],
)}
>
{flameFrames[frameIndex]}
</pre>
</div>
{/* Right flame (mirrored) */}
<div className="relative overflow-hidden -scale-x-100">
<pre
className={cn(
"text-heat-100 font-mono whitespace-pre",
sizeClasses[size],
)}
>
{flameFrames[frameIndex]}
</pre>
</div>
</div>
);
}