import * as LucideIcons from 'lucide-react'; import { cn } from '@/lib/utils'; import { Image, Calendar, User } from 'lucide-react'; interface Section { id: string; type: string; layoutVariant?: string; colorScheme?: string; props: Record; elementStyles?: Record; styles?: any; } interface FeatureGridRendererProps { section: Section; className?: string; } const COLOR_SCHEMES: Record = { default: { bg: '', text: 'text-gray-900', cardBg: 'bg-gray-50' }, primary: { bg: 'wn-primary-bg', text: 'text-white', cardBg: 'bg-white/10' }, secondary: { bg: 'wn-secondary-bg', text: 'text-white', cardBg: 'bg-white/10' }, muted: { bg: 'bg-gray-50', text: 'text-gray-700', cardBg: 'bg-white' }, }; const GRID_CLASSES: Record = { 'grid-2': 'grid-cols-1 md:grid-cols-2', 'grid-3': 'grid-cols-1 md:grid-cols-3', 'grid-4': 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4', }; // Default features for static demo const DEFAULT_FEATURES = [ { title: 'Fast Delivery', description: 'Quick shipping to your doorstep', icon: 'Truck' }, { title: 'Secure Payment', description: 'Your data is always protected', icon: 'Shield' }, { title: 'Quality Products', description: 'Only the best for our customers', icon: 'Star' }, ]; // Placeholder post-card skeleton shown when features are dynamic (related_posts) function PostCardPlaceholder({ index, cardBg }: { index: number; cardBg: string }) { const widths = ['w-3/4', 'w-2/3', 'w-4/5']; const titleWidth = widths[index % widths.length]; return (
{/* Thumbnail placeholder */}
{/* Meta row */}
Jan 1, 2025 Author
{/* Title skeleton */}
{/* Excerpt skeleton */}
{/* "Read more" chip */}
); } export function FeatureGridRenderer({ section, className }: FeatureGridRendererProps) { const scheme = COLOR_SCHEMES[section.colorScheme || 'default'] ?? COLOR_SCHEMES['default']; const layout = section.layoutVariant || 'grid-3'; const gridClass = GRID_CLASSES[layout] || GRID_CLASSES['grid-3']; const heading = section.props?.heading?.value || 'Our Features'; const featuresProp = section.props?.features; const isDynamic = featuresProp?.type === 'dynamic' && !!featuresProp?.source; const features = isDynamic ? [] : (featuresProp?.value || DEFAULT_FEATURES); // Determine how many placeholder post-cards to show (match grid columns) const placeholderCount = layout === 'grid-4' ? 4 : layout === 'grid-2' ? 2 : 3; // Helper to get text styles (including font family) const getTextStyles = (elementName: string) => { const styles = section.elementStyles?.[elementName] || {}; return { classNames: cn( styles.fontSize, styles.fontWeight, { 'font-sans': styles.fontFamily === 'secondary', 'font-serif': styles.fontFamily === 'primary', } ), style: { color: styles.color, textAlign: styles.textAlign, backgroundColor: styles.backgroundColor } }; }; const headingStyle = getTextStyles('heading'); const featureItemStyle = getTextStyles('feature_item'); // Helper to get background style for dynamic schemes const getBackgroundStyle = () => { if (scheme.bg === 'wn-gradient-bg') { return { backgroundImage: 'linear-gradient(135deg, var(--wn-gradient-start, #9333ea), var(--wn-gradient-end, #3b82f6))' }; } if (scheme.bg === 'wn-primary-bg') { return { backgroundColor: 'var(--wn-primary, #1a1a1a)' }; } if (scheme.bg === 'wn-secondary-bg') { return { backgroundColor: 'var(--wn-secondary, #6b7280)' }; } return undefined; }; const heightMap: Record = { 'default': 'py-12 md:py-20', 'small': 'py-8 md:py-12', 'medium': 'py-16 md:py-24', 'large': 'py-24 md:py-36', 'fullscreen': 'min-h-[50vh] flex flex-col justify-center', }; const customPadding = section.styles?.paddingTop || section.styles?.paddingBottom; const heightClasses = customPadding ? '' : (heightMap[section.styles?.heightPreset || 'default'] || 'py-12 md:py-20'); const hasCustomBackground = !!section.styles?.backgroundColor || !!section.styles?.backgroundImage || section.styles?.backgroundType === 'gradient'; return (
{heading && (

{heading}

)} {/* Dynamic (related posts) — show post-card skeleton placeholders */} {isDynamic ? (
{Array.from({ length: placeholderCount }).map((_, i) => ( ))}
) : ( /* Static items — regular icon feature cards */
{(Array.isArray(features) ? features : DEFAULT_FEATURES).map((feature: any, index: number) => { const IconComponent = (LucideIcons as any)[feature.icon] || LucideIcons.Star; return (

{feature.title || `Feature ${index + 1}`}

{feature.description || 'Feature description goes here'}

); })}
)}
); }