'use client'; import React, { useEffect, useRef } from 'react'; import Image from 'next/image'; import { cn } from '../../lib/utils'; import { Container } from '../ui/Container'; import { Button } from '../ui/Button'; // Hero height options type HeroHeight = 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'screen'; // Hero variant options type HeroVariant = 'default' | 'dark' | 'primary' | 'gradient'; interface HeroProps { title: string; subtitle?: string; backgroundImage?: string; backgroundAlt?: string; height?: HeroHeight; variant?: HeroVariant; ctaText?: string; ctaLink?: string; ctaVariant?: 'primary' | 'secondary' | 'outline'; overlay?: boolean; overlayOpacity?: number; children?: React.ReactNode; className?: string; // Additional props for background color and overlay backgroundColor?: string; colorOverlay?: string; overlayStrength?: number; // WordPress Salient-specific props enableGradient?: boolean; gradientDirection?: 'left_to_right' | 'right_to_left' | 'top_to_bottom' | 'bottom_to_top'; colorOverlay2?: string; parallaxBg?: boolean; parallaxBgSpeed?: 'slow' | 'fast' | 'medium'; bgImageAnimation?: 'none' | 'zoom-out-reveal' | 'fade-in'; topPadding?: string; bottomPadding?: string; textAlignment?: 'left' | 'center' | 'right'; textColor?: 'light' | 'dark'; shapeType?: string; scenePosition?: 'center' | 'top' | 'bottom'; fullScreenRowPosition?: 'middle' | 'top' | 'bottom'; // Video background props videoBg?: string; videoMp4?: string; videoWebm?: string; } // Helper function to get height styles const getHeightStyles = (height: HeroHeight, fullScreenRowPosition?: string) => { const baseHeight = { sm: 'min-h-[300px] md:min-h-[400px]', md: 'min-h-[400px] md:min-h-[500px]', lg: 'min-h-[500px] md:min-h-[600px]', xl: 'min-h-[600px] md:min-h-[700px]', full: 'min-h-screen', screen: 'min-h-screen' }[height] || 'min-h-[500px] md:min-h-[600px]'; // Handle full screen positioning if (fullScreenRowPosition === 'middle') { return `${baseHeight} flex items-center justify-center`; } else if (fullScreenRowPosition === 'top') { return `${baseHeight} items-start justify-center pt-12`; } else if (fullScreenRowPosition === 'bottom') { return `${baseHeight} items-end justify-center pb-12`; } return baseHeight; }; // Helper function to get variant styles const getVariantStyles = (variant: HeroVariant) => { switch (variant) { case 'dark': return 'bg-gray-900 text-white'; case 'primary': return 'bg-primary text-white'; case 'gradient': return 'bg-gradient-to-br from-primary to-secondary text-white'; default: return 'bg-gray-800 text-white'; } }; // Helper function to get overlay opacity const getOverlayOpacity = (opacity?: number) => { if (opacity === undefined) return 'bg-black/50'; if (opacity >= 1) return 'bg-black'; if (opacity <= 0) return 'bg-transparent'; return `bg-black/${Math.round(opacity * 100)}`; }; export const Hero: React.FC = ({ title, subtitle, backgroundImage, backgroundAlt = '', height = 'md', variant = 'default', ctaText, ctaLink, ctaVariant = 'primary', overlay = true, overlayOpacity, children, className = '', backgroundColor, colorOverlay, overlayStrength, enableGradient = false, gradientDirection = 'left_to_right', colorOverlay2, parallaxBg = false, parallaxBgSpeed = 'medium', bgImageAnimation = 'none', topPadding, bottomPadding, textAlignment = 'center', textColor = 'light', shapeType, scenePosition = 'center', fullScreenRowPosition, videoBg, videoMp4, videoWebm, }) => { const hasBackground = !!backgroundImage; const hasCTA = !!ctaText && !!ctaLink; const hasColorOverlay = !!colorOverlay; const hasGradient = !!enableGradient; const hasParallax = !!parallaxBg; const hasVideo = !!(videoMp4?.trim()) || !!(videoWebm?.trim()); const heroRef = useRef(null); const videoRef = useRef(null); // Calculate overlay opacity const overlayOpacityValue = overlayOpacity ?? (overlayStrength !== undefined ? overlayStrength : 0.5); // Get text alignment const textAlignClass = { left: 'text-left', center: 'text-center', right: 'text-right', }[textAlignment]; // Get text color const textColorClass = textColor === 'light' ? 'text-white' : 'text-gray-900'; const subtitleTextColorClass = textColor === 'light' ? 'text-gray-100' : 'text-gray-600'; // Get gradient direction const gradientDirectionClass = { 'left_to_right': 'bg-gradient-to-r', 'right_to_left': 'bg-gradient-to-l', 'top_to_bottom': 'bg-gradient-to-b', 'bottom_to_top': 'bg-gradient-to-t', }[gradientDirection]; // Get parallax speed const parallaxSpeedClass = { slow: 'parallax-slow', medium: 'parallax-medium', fast: 'parallax-fast', }[parallaxBgSpeed]; // Get background animation const bgAnimationClass = { none: '', 'zoom-out-reveal': 'animate-zoom-out', 'fade-in': 'animate-fade-in', }[bgImageAnimation]; // Calculate padding from props const customPaddingStyle = { paddingTop: topPadding || undefined, paddingBottom: bottomPadding || undefined, }; // Parallax effect handler useEffect(() => { if (!hasParallax || !heroRef.current) return; const handleScroll = () => { if (!heroRef.current) return; const rect = heroRef.current.getBoundingClientRect(); const viewportHeight = window.innerHeight; // Calculate offset based on scroll position const scrollProgress = (viewportHeight - rect.top) / (viewportHeight + rect.height); const offset = scrollProgress * 50; // Max 50px offset // Apply to CSS variable heroRef.current.style.setProperty('--parallax-offset', `${offset}px`); }; handleScroll(); // Initial call window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); }, [hasParallax]); return (
{/* Video Background */} {hasVideo && (
)} {/* Background Image with Parallax (fallback if no video) */} {hasBackground && !hasVideo && (
{backgroundAlt
)} {/* Background Variant (if no image) */} {!hasBackground && !backgroundColor && (
)} {/* Gradient Overlay */} {hasGradient && (
)} {/* Color Overlay (from WordPress color_overlay) */} {hasColorOverlay && (
)} {/* Second Color Overlay (for gradients) */} {colorOverlay2 && (
)} {/* Standard Overlay */} {overlay && hasBackground && !hasColorOverlay && (
)} {/* Shape Divider (bottom) */} {shapeType && (
{shapeType === 'waves_opacity_alt' && ( )} {shapeType === 'mountains' && ( )}
)} {/* Content */}
{/* Title */}

{title}

{/* Subtitle */} {subtitle && (

{subtitle}

)} {/* CTA Button */} {hasCTA && (
)} {/* Additional Content */} {children && (
{children}
)}
); }; // Sub-components for more complex hero layouts export const HeroContent: React.FC<{ title: string; subtitle?: string; children?: React.ReactNode; className?: string; }> = ({ title, subtitle, children, className = '' }) => (

{title}

{subtitle &&

{subtitle}

} {children}
); export const HeroActions: React.FC<{ children: React.ReactNode; className?: string; }> = ({ children, className = '' }) => (
{children}
); export default Hero;