content = $content;
}
public static function getCmsName(): string
{
return 'Hero Section';
}
public static function getCmsDescription(): string
{
return 'Large header section with headline, text and optional background image with call-to-action button';
}
public static function getCmsCategory(): string
{
return 'Layout';
}
public static function getCmsIcon(): string
{
return 'hero';
}
public static function getCmsTags(): array
{
return ['header', 'hero', 'banner', 'cta'];
}
public static function getCmsPreview(): string
{
return '
Hero Headline
Compelling subtitle text that draws attention
';
}
public static function getCmsFields(): array
{
return [
TextField::make('headline', 'Headline')
->translatable()
->required()
->maxLength(100)
->helpText('Main headline for the hero section'),
TextField::make('subheadline', 'Subheadline')
->translatable()
->maxLength(200)
->helpText('Supporting text below the main headline'),
WysiwygField::make('description', 'Description')
->translatable()
->basic()
->helpText('Additional descriptive text'),
TextField::make('cta_text', 'Button Text')
->translatable()
->maxLength(50)
->placeholder('Get Started'),
TextField::make('cta_link', 'Button Link')
->url()
->placeholder('https://example.com'),
BooleanField::make('cta_new_tab', 'Open Link in New Tab')
->default(false),
MediaField::make('background_image', 'Background Image')
->images()
->helpText('Optional background image for the hero section'),
BooleanField::make('dark_overlay', 'Dark Overlay')
->default(true)
->helpText('Add dark overlay for better text readability'),
TextField::make('text_alignment', 'Text Alignment')
->default('center')
->helpText('Text alignment: left, center, right'),
TextField::make('min_height', 'Minimum Height')
->default('500px')
->helpText('Minimum height of the hero section (e.g., 500px, 50vh)'),
];
}
public static function validateContent(array $content): array
{
$errors = [];
// Custom validation: If CTA text is provided, link must also be provided
$ctaText = $content['cta_text'] ?? [];
$ctaLink = $content['cta_link'] ?? '';
foreach ($ctaText as $locale => $text) {
if (! empty($text) && empty($ctaLink)) {
$errors['cta_link'] = ['Button link is required when button text is provided'];
break;
}
}
return $errors;
}
public function render()
{
return view('flux-cms-starter::components.hero-section');
}
// Helper methods for accessing content
protected function getHeadline(?string $locale = null): string
{
$locale = $locale ?? app()->getLocale();
return $this->content['headline'][$locale] ?? '';
}
protected function getSubheadline(?string $locale = null): string
{
$locale = $locale ?? app()->getLocale();
return $this->content['subheadline'][$locale] ?? '';
}
protected function getDescription(?string $locale = null): string
{
$locale = $locale ?? app()->getLocale();
return $this->content['description'][$locale] ?? '';
}
protected function getCtaText(?string $locale = null): string
{
$locale = $locale ?? app()->getLocale();
return $this->content['cta_text'][$locale] ?? '';
}
protected function getCtaLink(): string
{
return $this->content['cta_link'] ?? '';
}
protected function getTextAlignment(): string
{
return $this->content['text_alignment'] ?? 'center';
}
protected function getMinHeight(): string
{
return $this->content['min_height'] ?? '500px';
}
protected function hasCta(): bool
{
return ! empty($this->getCtaText()) && ! empty($this->getCtaLink());
}
protected function hasBackgroundImage(): bool
{
return ! empty($this->content['background_image']);
}
protected function getBackgroundImageUrl(): ?string
{
if (! $this->hasBackgroundImage()) {
return null;
}
$mediaId = $this->content['background_image'];
$media = \Spatie\MediaLibrary\MediaCollections\Models\Media::find($mediaId);
return $media?->getUrl('large') ?? $media?->getUrl();
}
protected function hasDarkOverlay(): bool
{
return $this->content['dark_overlay'] ?? true;
}
protected function opensInNewTab(): bool
{
return $this->content['cta_new_tab'] ?? false;
}
protected function getContainerClasses(): string
{
$classes = ['hero-section', 'relative', 'flex', 'items-center', 'justify-center'];
// Text alignment
$alignment = $this->getTextAlignment();
if ($alignment === 'left') {
$classes[] = 'text-left';
} elseif ($alignment === 'right') {
$classes[] = 'text-right';
} else {
$classes[] = 'text-center';
}
return implode(' ', $classes);
}
protected function getTextClasses(): string
{
$classes = ['relative', 'z-10'];
if ($this->hasBackgroundImage()) {
$classes[] = 'text-white';
}
return implode(' ', $classes);
}
}