import React from 'react'; import type { ComponentConfig } from '@measured/puck'; import { createDesignControlsFields, applyDesignControls, type DesignControlsProps, } from '../../theme'; import { imagePickerField } from '../../fields/ImagePickerField'; export interface HeroCtaButton { text: string; href: string; } export interface HeroMedia { type: 'image' | 'none'; src?: string; alt?: string; } export interface HeroProps extends DesignControlsProps { headline: string; subheadline: string; primaryCta: HeroCtaButton; secondaryCta?: HeroCtaButton; media?: HeroMedia; badge?: string; variant: 'centered' | 'split' | 'minimal'; fullWidth?: boolean; } const HeroRender: React.FC = (props) => { const { headline, subheadline, primaryCta, secondaryCta, media, badge, variant, fullWidth, ...designControls } = props; const applied = applyDesignControls(designControls); const isGradient = designControls.backgroundVariant === 'gradient'; const isDark = isGradient || designControls.backgroundVariant === 'dark'; const isSplit = variant === 'split'; const isMinimal = variant === 'minimal'; const containerClass = fullWidth ? 'w-full px-4 sm:px-6 lg:px-8' : `${applied.containerClassName || 'max-w-7xl'} mx-auto px-4 sm:px-6 lg:px-8`; return (
{/* Overlay for background images */} {designControls.backgroundImage && designControls.overlayStrength && (
)}
{/* Badge */} {badge && !isMinimal && (
{badge}
)} {/* Headline */}

{headline}

{/* Subheadline */}

{subheadline}

{/* CTAs */} {(primaryCta?.text || secondaryCta?.text) && (
{primaryCta?.text && ( {primaryCta.text} )} {secondaryCta?.text && ( {secondaryCta.text} )}
)}
{/* Media */} {media?.type === 'image' && media.src && (
{media.alt
)}
); }; const designControlFields = createDesignControlsFields(); export const Hero: ComponentConfig = { label: 'Hero', fields: { headline: { type: 'text', label: 'Headline', }, subheadline: { type: 'textarea', label: 'Subheadline', }, primaryCta: { type: 'object', label: 'Primary Button', objectFields: { text: { type: 'text', label: 'Button Text' }, href: { type: 'text', label: 'Button URL' }, }, }, secondaryCta: { type: 'object', label: 'Secondary Button (optional)', objectFields: { text: { type: 'text', label: 'Button Text' }, href: { type: 'text', label: 'Button URL' }, }, }, media: { type: 'object', label: 'Media', objectFields: { type: { type: 'select', label: 'Type', options: [ { label: 'None', value: 'none' }, { label: 'Image', value: 'image' }, ], }, src: { ...imagePickerField, label: 'Image' }, alt: { type: 'text', label: 'Alt Text' }, }, }, badge: { type: 'text', label: 'Badge Text (optional)', }, variant: { type: 'select', label: 'Layout Variant', options: [ { label: 'Centered', value: 'centered' }, { label: 'Split (text + media)', value: 'split' }, { label: 'Minimal', value: 'minimal' }, ], }, fullWidth: { type: 'radio', label: 'Full Width', options: [ { label: 'No', value: false }, { label: 'Yes', value: true }, ], }, // Design Controls padding: designControlFields.padding, backgroundVariant: designControlFields.backgroundVariant, gradientPreset: designControlFields.gradientPreset, backgroundImage: designControlFields.backgroundImage, overlayStrength: designControlFields.overlayStrength, contentMaxWidth: designControlFields.contentMaxWidth, alignment: designControlFields.alignment, hideOnMobile: designControlFields.hideOnMobile, hideOnTablet: designControlFields.hideOnTablet, hideOnDesktop: designControlFields.hideOnDesktop, anchorId: designControlFields.anchorId, }, defaultProps: { headline: 'Your headline goes here', subheadline: 'Add a compelling subheadline that describes what you offer.', primaryCta: { text: 'Get Started', href: '#', }, variant: 'centered', fullWidth: false, backgroundVariant: 'none', padding: 'xl', contentMaxWidth: 'wide', alignment: 'center', }, render: HeroRender, }; export default Hero;