'use client'; import React, { useEffect, useRef } from 'react'; import Image from 'next/image'; import { cn } from '../../lib/utils'; import { Container } from '../ui/Container'; // Section background options type SectionBackground = 'default' | 'light' | 'dark' | 'primary' | 'secondary' | 'gradient'; // Section padding options type SectionPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'; interface SectionProps { children: React.ReactNode; background?: SectionBackground; padding?: SectionPadding; fullWidth?: boolean; className?: string; id?: string; as?: React.ElementType; // Additional props for background images and overlays backgroundImage?: string; backgroundAlt?: string; colorOverlay?: string; overlayOpacity?: number; backgroundColor?: string; // 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'; // Additional styling borderRadius?: string; boxShadow?: boolean; // Video background props videoBg?: string; videoMp4?: string; videoWebm?: string; } // Helper function to get background styles const getBackgroundStyles = (background: SectionBackground) => { switch (background) { case 'light': return 'bg-gray-50'; case 'dark': return 'bg-gray-900 text-white'; case 'primary': return 'bg-primary text-white'; case 'secondary': return 'bg-secondary text-white'; case 'gradient': return 'bg-gradient-to-br from-primary to-secondary text-white'; default: return 'bg-white'; } }; // Helper function to get padding styles const getPaddingStyles = (padding: SectionPadding) => { switch (padding) { case 'none': return 'py-0'; case 'sm': return 'py-4 sm:py-6'; case 'md': return 'py-8 sm:py-12'; case 'lg': return 'py-12 sm:py-16'; case 'xl': return 'py-16 sm:py-20 md:py-24'; case '2xl': return 'py-20 sm:py-24 md:py-32'; default: return 'py-12 sm:py-16'; } }; export const Section: React.FC = ({ children, background = 'default', padding = 'md', fullWidth = false, className = '', id, as: Component = 'section', backgroundImage, backgroundAlt = '', colorOverlay, overlayOpacity = 0.5, backgroundColor, enableGradient = false, gradientDirection = 'left_to_right', colorOverlay2, parallaxBg = false, parallaxBgSpeed = 'medium', bgImageAnimation = 'none', topPadding, bottomPadding, textAlignment = 'left', textColor = 'dark', shapeType, scenePosition = 'center', fullScreenRowPosition, borderRadius, boxShadow = false, videoBg, videoMp4, videoWebm, }) => { const hasBackgroundImage = !!backgroundImage; const hasColorOverlay = !!colorOverlay; const hasCustomBg = !!backgroundColor; const hasGradient = !!enableGradient; const hasParallax = !!parallaxBg; const hasVideo = !!(videoMp4?.trim()) || !!(videoWebm?.trim()); const sectionRef = useRef(null); const videoRef = useRef(null); // 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'; // 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, }; // Base classes const baseClasses = cn( 'w-full relative overflow-hidden', getPaddingStyles(padding), textAlignClass, textColorClass, boxShadow && 'shadow-xl', borderRadius && `rounded-${borderRadius}`, className ); // Background style (for solid colors) const backgroundStyle = hasCustomBg ? { backgroundColor, ...customPaddingStyle } : customPaddingStyle; // Content wrapper classes const contentWrapperClasses = cn( 'relative z-20 w-full', !fullWidth && 'container mx-auto px-4 md:px-6' ); // Parallax effect handler useEffect(() => { if (!hasParallax || !sectionRef.current) return; const handleScroll = () => { if (!sectionRef.current) return; const rect = sectionRef.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 sectionRef.current.style.setProperty('--parallax-offset', `${offset}px`); }; handleScroll(); // Initial call window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); }, [hasParallax]); const content = (
{/* Video Background */} {hasVideo && (
)} {/* Background Image with Parallax (fallback if no video) */} {hasBackgroundImage && !hasVideo && (
{backgroundAlt
)} {/* Background Variant (if no image) */} {!hasBackgroundImage && !hasCustomBg && (
)} {/* Gradient Overlay */} {hasGradient && (
)} {/* Color Overlay (from WordPress color_overlay) */} {hasColorOverlay && (
)} {/* Second Color Overlay (for gradients) */} {colorOverlay2 && (
)} {/* Shape Divider (bottom) */} {shapeType && (
{shapeType === 'waves_opacity_alt' && ( )} {shapeType === 'mountains' && ( )}
)} {/* Content */}
{fullWidth ? children : ( {children} )}
); if (Component !== 'section') { return ( {/* Video Background */} {hasVideo && (
)} {/* Background Image with Parallax (fallback if no video) */} {hasBackgroundImage && !hasVideo && (
{backgroundAlt
)} {/* Background Variant (if no image) */} {!hasBackgroundImage && !hasCustomBg && (
)} {/* Gradient Overlay */} {hasGradient && (
)} {/* Color Overlay */} {hasColorOverlay && (
)} {/* Second Color Overlay */} {colorOverlay2 && (
)} {/* Shape Divider */} {shapeType && (
{shapeType === 'waves_opacity_alt' && ( )} {shapeType === 'mountains' && ( )}
)}
{fullWidth ? children : ( {children} )}
); } return content; }; // Sub-components for common section patterns export const SectionHeader: React.FC<{ title: string; subtitle?: string; align?: 'left' | 'center' | 'right'; className?: string; }> = ({ title, subtitle, align = 'center', className = '' }) => { const alignment = { left: 'text-left', center: 'text-center', right: 'text-right', }[align]; return (

{title}

{subtitle && (

{subtitle}

)}
); }; export const SectionContent: React.FC<{ children: React.ReactNode; className?: string; }> = ({ children, className = '' }) => (
{children}
); export const SectionGrid: React.FC<{ children: React.ReactNode; cols?: 1 | 2 | 3 | 4; gap?: 'sm' | 'md' | 'lg' | 'xl'; className?: string; }> = ({ children, cols = 3, gap = 'md', className = '' }) => { const gapClasses = { sm: 'gap-4 md:gap-6', md: 'gap-6 md:gap-8', lg: 'gap-8 md:gap-12', xl: 'gap-10 md:gap-16', }[gap]; const colClasses = { 1: 'grid-cols-1', 2: 'grid-cols-1 md:grid-cols-2', 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4', }[cols]; return (
{children}
); }; export default Section;