infoalloggi-monorepo/apps/infoalloggi/src/components/videoPlayer.tsx

109 lines
2.7 KiB
TypeScript

"use client";
import { AnimatePresence, motion, useInView } from "framer-motion";
import { Play } from "lucide-react";
import Image from "next/image";
import { useEffect, useRef, useState } from "react";
import { cn } from "~/lib/utils";
interface VideoPlayerProps {
coverImage: string;
videoSrc: string;
title?: string;
aspectRatio?: "square" | "video" | "vertical";
className?: string;
}
export function VideoPlayer({
coverImage,
videoSrc,
title,
aspectRatio = "video",
className,
}: VideoPlayerProps) {
const [isPlaying, setIsPlaying] = useState(false);
const videoRef = useRef<HTMLDivElement>(null);
const inView = useInView(videoRef);
useEffect(() => {
if (!inView) {
setIsPlaying(false);
}
}, [inView]);
const aspectRatioClasses = {
square: "aspect-square",
vertical: "aspect-[9/16]",
video: "aspect-video",
};
return (
<div
className={cn(
"relative w-full overflow-hidden rounded-lg",
aspectRatioClasses[aspectRatio],
className,
)}
ref={videoRef}
>
<AnimatePresence mode="wait">
{!isPlaying ? (
<motion.div
animate={{ opacity: 1 }}
className="relative h-full w-full cursor-pointer"
exit={{ opacity: 0 }}
initial={{ opacity: 0 }}
key="cover"
onClick={() => setIsPlaying(true)}
transition={{ duration: 0.3 }}
>
<Image
alt={title || "Video thumbnail"}
className="object-cover"
fill
priority
src={coverImage || "/fallback-video.png"}
/>
<div className="absolute inset-0 flex items-center justify-center bg-black/20">
<motion.div
className="flex size-16 items-center justify-center rounded-full bg-primary/90 text-primary-foreground shadow-lg"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
>
<Play className="size-8" />
</motion.div>
</div>
{title && (
<div className="absolute right-0 bottom-0 left-0 bg-linear-to-t from-black/80 to-transparent p-4">
<h3 className="font-medium text-lg text-white">{title}</h3>
</div>
)}
</motion.div>
) : (
<motion.div
animate={{ opacity: 1 }}
className="h-full w-full"
exit={{ opacity: 0 }}
initial={{ opacity: 0 }}
key="video"
transition={{ duration: 0.3 }}
>
<video
autoPlay
className="h-full w-full rounded-md"
controls
controlsList="play nodownload"
disablePictureInPicture
disableRemotePlayback
muted
onEnded={() => setIsPlaying(false)}
src={videoSrc}
>
Your browser does not support the video tag.
</video>
</motion.div>
)}
</AnimatePresence>
</div>
);
}