95eb362bfc
QuantumLab template converted to Next.js 16 + React 19 + TypeScript: - 8 page routes (home, about, blog, contact, careers, team-members, coming-soon, 404) - Dynamic routes for blog posts, career positions, and team members - GSAP animations (marquee, counters, button hovers) - IntersectionObserver-based scroll reveal (blur-to-clear transitions) - Dark mode with next-themes - React Hook Form + Zod contact form - Framer Motion page transitions - Lottie animations via lottie-web Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
39 lines
979 B
TypeScript
39 lines
979 B
TypeScript
"use client"
|
|
|
|
import { useEffect, useRef } from "react"
|
|
|
|
interface LottiePlayerProps {
|
|
src: string
|
|
className?: string
|
|
loop?: boolean
|
|
autoplay?: boolean
|
|
style?: React.CSSProperties
|
|
}
|
|
|
|
export default function LottiePlayer({ src, className, loop = true, autoplay = true, style }: LottiePlayerProps) {
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
const animRef = useRef<ReturnType<typeof import("lottie-web").default.loadAnimation> | null>(null)
|
|
|
|
useEffect(() => {
|
|
let cancelled = false
|
|
|
|
import("lottie-web").then((lottie) => {
|
|
if (cancelled || !containerRef.current) return
|
|
animRef.current = lottie.default.loadAnimation({
|
|
container: containerRef.current,
|
|
renderer: "svg",
|
|
loop,
|
|
autoplay,
|
|
path: src,
|
|
})
|
|
})
|
|
|
|
return () => {
|
|
cancelled = true
|
|
animRef.current?.destroy()
|
|
}
|
|
}, [src, loop, autoplay])
|
|
|
|
return <div ref={containerRef} className={className} style={style} />
|
|
}
|