3 Commits

View File

@@ -6,6 +6,7 @@ import HeroBackgrounds, { type HeroBackgroundVariantProps } from "@/components/b
import LogoMarquee, { type MarqueeItem } from "@/components/shared/LogoMarquee"; import LogoMarquee, { type MarqueeItem } from "@/components/shared/LogoMarquee";
import { cls } from "@/lib/utils"; import { cls } from "@/lib/utils";
import { useButtonAnimation } from "@/components/hooks/useButtonAnimation"; import { useButtonAnimation } from "@/components/hooks/useButtonAnimation";
import { useState } from "react";
import type { LucideIcon } from "lucide-react"; import type { LucideIcon } from "lucide-react";
import type { ButtonConfig, ButtonAnimationType } from "@/types/button"; import type { ButtonConfig, ButtonAnimationType } from "@/types/button";
import type { Avatar } from "@/components/shared/AvatarGroup"; import type { Avatar } from "@/components/shared/AvatarGroup";
@@ -70,45 +71,46 @@ interface HeroBillboardProps {
} }
const HeroBillboard = ({ const HeroBillboard = ({
title, title,
description, description,
background, background,
tag, tag,
tagIcon, tagIcon,
tagAnimation, tagAnimation,
buttons, buttons,
buttonAnimation, buttonAnimation,
avatars, avatars,
avatarText, avatarText,
imageSrc, imageSrc,
videoSrc, videoSrc,
imageAlt = "", imageAlt = "",
videoAriaLabel = "Hero video", videoAriaLabel = "Hero video",
mediaAnimation = "none", mediaAnimation = "none",
marqueeItems, marqueeItems,
marqueeSpeed = 30, marqueeSpeed = 30,
showMarqueeCard = true, showMarqueeCard = true,
ariaLabel = "Hero section", ariaLabel = "Hero section",
className = "", className = "",
containerClassName = "", containerClassName = "",
textBoxClassName = "", textBoxClassName = "",
titleClassName = "", titleClassName = "",
descriptionClassName = "", descriptionClassName = "",
tagClassName = "", tagClassName = "",
avatarGroupClassName = "", avatarGroupClassName = "",
buttonContainerClassName = "", buttonContainerClassName = "",
buttonClassName = "", buttonClassName = "",
buttonTextClassName = "", buttonTextClassName = "",
mediaWrapperClassName = "", mediaWrapperClassName = "",
imageClassName = "", imageClassName = "",
marqueeClassName = "", marqueeClassName = "",
marqueeItemClassName = "", marqueeItemClassName = "",
marqueeCardClassName = "", marqueeCardClassName = "",
marqueeImageClassName = "", marqueeImageClassName = "",
marqueeTextClassName = "", marqueeTextClassName = "",
marqueeIconClassName = "", marqueeIconClassName = "",
}: HeroBillboardProps) => { }: HeroBillboardProps) => {
const { containerRef: mediaContainerRef } = useButtonAnimation({ animationType: mediaAnimation }); const { containerRef: mediaContainerRef } = useButtonAnimation({ animationType: mediaAnimation });
const [isHovering, setIsHovering] = useState(false);
return ( return (
<section <section
@@ -139,17 +141,35 @@ const HeroBillboard = ({
center={true} center={true}
/> />
<div className="flex flex-col gap-6" > <div className="flex flex-col gap-6" >
<div ref={mediaContainerRef} className={cls("w-full overflow-hidden rounded-theme-capped card p-4 [perspective:1000px]", mediaWrapperClassName)}> <div
<div className="w-full h-full transition-transform duration-500 [transform-style:preserve-3d] hover:[transform:rotateX(180deg)]"> ref={mediaContainerRef}
<MediaContent className={cls("w-full overflow-hidden rounded-theme-capped card p-4 [perspective:1000px]", mediaWrapperClassName)}
imageSrc={imageSrc} onMouseEnter={() => setIsHovering(true)}
videoSrc={videoSrc} onMouseLeave={() => setIsHovering(false)}
imageAlt={imageAlt} >
videoAriaLabel={videoAriaLabel} <style>{`
imageClassName={cls("z-1 aspect-square md:aspect-video", imageClassName)} @keyframes infiniteSpin {
/> from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.spin-on-hover {
animation: infiniteSpin 8s linear infinite;
}
`}</style>
<div className={cls("w-full h-full [transform-style:preserve-3d]", isHovering && "spin-on-hover")}>
<MediaContent
imageSrc={imageSrc}
videoSrc={videoSrc}
imageAlt={imageAlt}
videoAriaLabel={videoAriaLabel}
imageClassName={cls("z-1 aspect-square md:aspect-video", imageClassName)}
/>
</div>
</div> </div>
</div>
{marqueeItems && marqueeItems.length > 0 && ( {marqueeItems && marqueeItems.length > 0 && (
<LogoMarquee <LogoMarquee
items={marqueeItems} items={marqueeItems}