feat: add HeroSliderBlock for multi-slide hero sections

- Add HeroSliderBlock with 1-10 slides support
- Each slide: background image (desktop + mobile), headline, subline, overlay, 2 CTAs
- Animation types: fade, slide, zoom, flip, none
- Autoplay with configurable interval, pause on hover/interaction
- Navigation: arrows (multiple styles), dots (dots/lines/numbers/thumbnails/progress)
- Touch swipe and keyboard navigation support
- Responsive height settings (desktop + mobile)
- Accessibility: ARIA labels, reduced motion support
- Add migration and update documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Martin Porwoll 2025-12-13 14:57:13 +00:00
parent 669f27d238
commit 4f6280e09e
8 changed files with 25938 additions and 1 deletions

View file

@ -551,6 +551,62 @@ SELECT * FROM audit_logs ORDER BY created_at DESC LIMIT 10;
\dt -- Alle Tabellen
```
## Blocks Übersicht
| Block | Slug | Beschreibung |
|-------|------|--------------|
| HeroBlock | hero-block | Einzelner Hero mit Bild, Headline, CTA |
| HeroSliderBlock | hero-slider-block | Hero-Slider mit mehreren Slides |
| TextBlock | text-block | Textinhalt mit Rich-Text |
| ImageTextBlock | image-text-block | Bild + Text nebeneinander |
| CardGridBlock | card-grid-block | Karten-Raster |
| QuoteBlock | quote-block | Zitat |
| CTABlock | cta-block | Call-to-Action |
| ContactFormBlock | contact-form-block | Kontaktformular |
| TimelineBlock | timeline-block | Timeline-Darstellung |
| DividerBlock | divider-block | Trennlinie |
| VideoBlock | video-block | Video einbetten |
| PostsListBlock | posts-list-block | Beitrags-Liste |
| TestimonialsBlock | testimonials-block | Kundenbewertungen |
| NewsletterBlock | newsletter-block | Newsletter-Anmeldung |
| ProcessStepsBlock | process-steps-block | Prozess-Schritte |
| FAQBlock | faq-block | FAQ-Akkordeon |
| TeamBlock | team-block | Team-Mitglieder |
| ServicesBlock | services-block | Leistungen |
### HeroSliderBlock Features
Vollwertiger Hero-Slider mit:
**Slides (Array, 1-10):**
- Hintergrundbild (Desktop + optional Mobil)
- Headline + Subline (lokalisiert)
- Text-Ausrichtung (links/zentriert/rechts)
- Vertikale Position (oben/mitte/unten)
- Overlay (Farbe, Deckkraft, Gradient)
- Primärer + Sekundärer CTA-Button
- Textfarbe (weiß/dunkel/primär)
**Animationen:**
- Typen: fade, slide, zoom, flip, none
- Konfigurierbare Dauer (300-1200ms)
**Autoplay:**
- Intervall (3-10 Sekunden)
- Pause bei Hover
- Pause bei Interaktion
**Navigation:**
- Pfeile (verschiedene Stile, Positionen)
- Dots (Punkte, Striche, Nummern, Thumbnails, Fortschritt)
- Touch-Swipe
- Tastaturnavigation
**Layout:**
- Höhe (Vollbild bis kompakt)
- Separate Mobile-Höhe
- Content-Breite
## Collections Übersicht
| Collection | Slug | Beschreibung |

View file

@ -0,0 +1,615 @@
import type { Block } from 'payload'
/**
* HeroSliderBlock
*
* Ein vollwertiger Hero-Slider mit:
* - Mehreren Slides (Bild, Headline, Subline, CTA)
* - Verschiedenen Animationstypen
* - Autoplay-Einstellungen
* - Navigationsoptionen (Dots, Pfeile)
* - Responsive Höheneinstellungen
*/
export const HeroSliderBlock: Block = {
slug: 'hero-slider-block',
labels: {
singular: 'Hero Slider',
plural: 'Hero Slider',
},
imageURL: '/assets/blocks/hero-slider.png',
fields: [
// Slides Array
{
name: 'slides',
type: 'array',
required: true,
minRows: 1,
maxRows: 10,
label: 'Slides',
labels: {
singular: 'Slide',
plural: 'Slides',
},
admin: {
description: 'Mindestens 1 Slide erforderlich, maximal 10 Slides',
initCollapsed: false,
},
fields: [
// Hintergrundbild
{
name: 'backgroundImage',
type: 'upload',
relationTo: 'media',
required: true,
label: 'Hintergrundbild',
admin: {
description: 'Empfohlen: 1920x1080px oder größer',
},
},
// Mobile Hintergrundbild (optional)
{
name: 'mobileBackgroundImage',
type: 'upload',
relationTo: 'media',
label: 'Mobiles Hintergrundbild',
admin: {
description: 'Optional: Alternatives Bild für mobile Geräte (Portrait-Format empfohlen)',
},
},
// Headline
{
name: 'headline',
type: 'text',
required: true,
label: 'Überschrift',
localized: true,
admin: {
description: 'Hauptüberschrift des Slides',
},
},
// Subline
{
name: 'subline',
type: 'textarea',
label: 'Unterüberschrift',
localized: true,
admin: {
description: 'Optionaler Untertitel oder kurze Beschreibung',
},
},
// Text-Ausrichtung
{
name: 'textAlignment',
type: 'select',
defaultValue: 'center',
label: 'Text-Ausrichtung',
options: [
{ label: 'Links', value: 'left' },
{ label: 'Zentriert', value: 'center' },
{ label: 'Rechts', value: 'right' },
],
},
// Vertikale Position
{
name: 'verticalPosition',
type: 'select',
defaultValue: 'center',
label: 'Vertikale Position',
options: [
{ label: 'Oben', value: 'top' },
{ label: 'Mitte', value: 'center' },
{ label: 'Unten', value: 'bottom' },
],
},
// Overlay
{
name: 'overlay',
type: 'group',
label: 'Overlay',
fields: [
{
name: 'enabled',
type: 'checkbox',
defaultValue: true,
label: 'Overlay aktivieren',
},
{
name: 'color',
type: 'select',
defaultValue: 'dark',
label: 'Overlay-Farbe',
options: [
{ label: 'Dunkel (Schwarz)', value: 'dark' },
{ label: 'Hell (Weiß)', value: 'light' },
{ label: 'Primärfarbe', value: 'primary' },
{ label: 'Gradient (Dunkel unten)', value: 'gradient-bottom' },
{ label: 'Gradient (Dunkel oben)', value: 'gradient-top' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'opacity',
type: 'select',
defaultValue: '50',
label: 'Deckkraft',
options: [
{ label: '20%', value: '20' },
{ label: '30%', value: '30' },
{ label: '40%', value: '40' },
{ label: '50%', value: '50' },
{ label: '60%', value: '60' },
{ label: '70%', value: '70' },
{ label: '80%', value: '80' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
],
},
// Primärer CTA
{
name: 'primaryCta',
type: 'group',
label: 'Primärer Button',
fields: [
{
name: 'enabled',
type: 'checkbox',
defaultValue: true,
label: 'Button anzeigen',
},
{
name: 'text',
type: 'text',
label: 'Button-Text',
localized: true,
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'link',
type: 'text',
label: 'Link',
admin: {
description: 'URL oder interner Pfad (z.B. /kontakt)',
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'style',
type: 'select',
defaultValue: 'primary',
label: 'Button-Stil',
options: [
{ label: 'Primär (gefüllt)', value: 'primary' },
{ label: 'Sekundär', value: 'secondary' },
{ label: 'Outline (Weiß)', value: 'outline-white' },
{ label: 'Outline (Dunkel)', value: 'outline-dark' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'openInNewTab',
type: 'checkbox',
defaultValue: false,
label: 'In neuem Tab öffnen',
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
],
},
// Sekundärer CTA
{
name: 'secondaryCta',
type: 'group',
label: 'Sekundärer Button',
fields: [
{
name: 'enabled',
type: 'checkbox',
defaultValue: false,
label: 'Button anzeigen',
},
{
name: 'text',
type: 'text',
label: 'Button-Text',
localized: true,
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'link',
type: 'text',
label: 'Link',
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'style',
type: 'select',
defaultValue: 'outline-white',
label: 'Button-Stil',
options: [
{ label: 'Primär (gefüllt)', value: 'primary' },
{ label: 'Sekundär', value: 'secondary' },
{ label: 'Outline (Weiß)', value: 'outline-white' },
{ label: 'Outline (Dunkel)', value: 'outline-dark' },
{ label: 'Text-Link', value: 'text' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'openInNewTab',
type: 'checkbox',
defaultValue: false,
label: 'In neuem Tab öffnen',
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
],
},
// Textfarbe
{
name: 'textColor',
type: 'select',
defaultValue: 'white',
label: 'Textfarbe',
options: [
{ label: 'Weiß', value: 'white' },
{ label: 'Dunkel', value: 'dark' },
{ label: 'Primärfarbe', value: 'primary' },
],
},
],
},
// Slider-Einstellungen
{
name: 'settings',
type: 'group',
label: 'Slider-Einstellungen',
fields: [
// Animation
{
name: 'animation',
type: 'select',
defaultValue: 'fade',
label: 'Animationstyp',
options: [
{ label: 'Überblenden (Fade)', value: 'fade' },
{ label: 'Schieben (Slide)', value: 'slide' },
{ label: 'Zoom', value: 'zoom' },
{ label: 'Flip', value: 'flip' },
{ label: 'Keine Animation', value: 'none' },
],
admin: {
description: 'Art des Übergangs zwischen den Slides',
},
},
// Animationsdauer
{
name: 'animationDuration',
type: 'select',
defaultValue: '500',
label: 'Animationsdauer',
options: [
{ label: 'Schnell (300ms)', value: '300' },
{ label: 'Normal (500ms)', value: '500' },
{ label: 'Langsam (800ms)', value: '800' },
{ label: 'Sehr langsam (1200ms)', value: '1200' },
],
},
// Autoplay
{
name: 'autoplay',
type: 'group',
label: 'Autoplay',
fields: [
{
name: 'enabled',
type: 'checkbox',
defaultValue: true,
label: 'Autoplay aktivieren',
},
{
name: 'interval',
type: 'select',
defaultValue: '5000',
label: 'Intervall',
options: [
{ label: '3 Sekunden', value: '3000' },
{ label: '4 Sekunden', value: '4000' },
{ label: '5 Sekunden', value: '5000' },
{ label: '6 Sekunden', value: '6000' },
{ label: '7 Sekunden', value: '7000' },
{ label: '8 Sekunden', value: '8000' },
{ label: '10 Sekunden', value: '10000' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'pauseOnHover',
type: 'checkbox',
defaultValue: true,
label: 'Bei Hover pausieren',
admin: {
description: 'Autoplay pausiert, wenn der Mauszeiger über dem Slider ist',
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'pauseOnInteraction',
type: 'checkbox',
defaultValue: true,
label: 'Bei Interaktion pausieren',
admin: {
description: 'Autoplay pausiert nach manueller Navigation',
condition: (_, siblingData) => siblingData?.enabled,
},
},
],
},
// Loop
{
name: 'loop',
type: 'checkbox',
defaultValue: true,
label: 'Endlosschleife',
admin: {
description: 'Nach dem letzten Slide automatisch zum ersten springen',
},
},
],
},
// Navigations-Einstellungen
{
name: 'navigation',
type: 'group',
label: 'Navigation',
fields: [
// Pfeile
{
name: 'arrows',
type: 'group',
label: 'Pfeile',
fields: [
{
name: 'enabled',
type: 'checkbox',
defaultValue: true,
label: 'Pfeile anzeigen',
},
{
name: 'style',
type: 'select',
defaultValue: 'default',
label: 'Pfeil-Stil',
options: [
{ label: 'Standard (Kreis)', value: 'default' },
{ label: 'Minimal', value: 'minimal' },
{ label: 'Eckig', value: 'square' },
{ label: 'Nur bei Hover', value: 'hover-only' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'position',
type: 'select',
defaultValue: 'sides',
label: 'Position',
options: [
{ label: 'Seitlich', value: 'sides' },
{ label: 'Unten links', value: 'bottom-left' },
{ label: 'Unten rechts', value: 'bottom-right' },
{ label: 'Unten zentriert', value: 'bottom-center' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'hideOnMobile',
type: 'checkbox',
defaultValue: false,
label: 'Auf Mobilgeräten ausblenden',
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
],
},
// Dots
{
name: 'dots',
type: 'group',
label: 'Punkte (Dots)',
fields: [
{
name: 'enabled',
type: 'checkbox',
defaultValue: true,
label: 'Punkte anzeigen',
},
{
name: 'style',
type: 'select',
defaultValue: 'dots',
label: 'Punkt-Stil',
options: [
{ label: 'Punkte (rund)', value: 'dots' },
{ label: 'Striche', value: 'lines' },
{ label: 'Nummern', value: 'numbers' },
{ label: 'Thumbnails', value: 'thumbnails' },
{ label: 'Fortschrittsbalken', value: 'progress' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'position',
type: 'select',
defaultValue: 'bottom-center',
label: 'Position',
options: [
{ label: 'Unten zentriert', value: 'bottom-center' },
{ label: 'Unten links', value: 'bottom-left' },
{ label: 'Unten rechts', value: 'bottom-right' },
{ label: 'Links vertikal', value: 'left' },
{ label: 'Rechts vertikal', value: 'right' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
{
name: 'color',
type: 'select',
defaultValue: 'white',
label: 'Farbe',
options: [
{ label: 'Weiß', value: 'white' },
{ label: 'Dunkel', value: 'dark' },
{ label: 'Primärfarbe', value: 'primary' },
],
admin: {
condition: (_, siblingData) => siblingData?.enabled,
},
},
],
},
// Swipe auf Touch-Geräten
{
name: 'swipe',
type: 'checkbox',
defaultValue: true,
label: 'Touch-Swipe aktivieren',
admin: {
description: 'Ermöglicht Wischen auf Touch-Geräten',
},
},
// Tastaturnavigation
{
name: 'keyboard',
type: 'checkbox',
defaultValue: true,
label: 'Tastaturnavigation',
admin: {
description: 'Navigation mit Pfeiltasten ermöglichen',
},
},
],
},
// Layout-Einstellungen
{
name: 'layout',
type: 'group',
label: 'Layout',
fields: [
// Höhe
{
name: 'height',
type: 'select',
defaultValue: 'viewport',
label: 'Höhe',
options: [
{ label: 'Vollbild (100vh)', value: 'viewport' },
{ label: 'Groß (80vh)', value: 'large' },
{ label: 'Mittel (60vh)', value: 'medium' },
{ label: 'Klein (40vh)', value: 'small' },
{ label: 'Kompakt (400px)', value: 'compact' },
{ label: 'Auto (Bildverhältnis)', value: 'auto' },
],
},
// Mobile Höhe
{
name: 'mobileHeight',
type: 'select',
defaultValue: 'viewport',
label: 'Mobile Höhe',
options: [
{ label: 'Wie Desktop', value: 'same' },
{ label: 'Vollbild (100vh)', value: 'viewport' },
{ label: 'Groß (80vh)', value: 'large' },
{ label: 'Mittel (60vh)', value: 'medium' },
{ label: 'Klein (50vh)', value: 'small' },
{ label: 'Kompakt (300px)', value: 'compact' },
],
},
// Content-Breite
{
name: 'contentWidth',
type: 'select',
defaultValue: 'container',
label: 'Inhaltsbreite',
options: [
{ label: 'Container (max-width)', value: 'container' },
{ label: 'Schmal', value: 'narrow' },
{ label: 'Breit', value: 'wide' },
{ label: 'Volle Breite', value: 'full' },
],
},
// Volle Breite (Edge-to-Edge)
{
name: 'fullWidth',
type: 'checkbox',
defaultValue: true,
label: 'Volle Bildschirmbreite',
admin: {
description: 'Slider nimmt die volle Bildschirmbreite ein',
},
},
],
},
// Accessibility
{
name: 'accessibility',
type: 'group',
label: 'Barrierefreiheit',
admin: {
condition: () => true, // Immer sichtbar, aber eingeklappt
},
fields: [
{
name: 'ariaLabel',
type: 'text',
defaultValue: 'Hero Slider',
label: 'ARIA Label',
localized: true,
admin: {
description: 'Beschreibung für Screenreader',
},
},
{
name: 'reducedMotion',
type: 'checkbox',
defaultValue: true,
label: 'Reduzierte Bewegung respektieren',
admin: {
description: 'Autoplay deaktivieren, wenn der User "prefers-reduced-motion" aktiviert hat',
},
},
],
},
],
}

View file

@ -1,4 +1,5 @@
export { HeroBlock } from './HeroBlock'
export { HeroSliderBlock } from './HeroSliderBlock'
export { TextBlock } from './TextBlock'
export { ImageTextBlock } from './ImageTextBlock'
export { CardGridBlock } from './CardGridBlock'

View file

@ -1,6 +1,7 @@
import type { CollectionConfig } from 'payload'
import {
HeroBlock,
HeroSliderBlock,
TextBlock,
ImageTextBlock,
CardGridBlock,
@ -73,6 +74,7 @@ export const Pages: CollectionConfig = {
blocks: [
// Bestehende Blocks
HeroBlock,
HeroSliderBlock,
TextBlock,
ImageTextBlock,
CardGridBlock,

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,133 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_slides_text_alignment" AS ENUM('left', 'center', 'right');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_slides_vertical_position" AS ENUM('top', 'center', 'bottom');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_slides_overlay_color" AS ENUM('dark', 'light', 'primary', 'gradient-bottom', 'gradient-top');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_slides_overlay_opacity" AS ENUM('20', '30', '40', '50', '60', '70', '80');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_slides_primary_cta_style" AS ENUM('primary', 'secondary', 'outline-white', 'outline-dark');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_slides_secondary_cta_style" AS ENUM('primary', 'secondary', 'outline-white', 'outline-dark', 'text');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_slides_text_color" AS ENUM('white', 'dark', 'primary');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_settings_animation" AS ENUM('fade', 'slide', 'zoom', 'flip', 'none');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_settings_animation_duration" AS ENUM('300', '500', '800', '1200');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_settings_autoplay_interval" AS ENUM('3000', '4000', '5000', '6000', '7000', '8000', '10000');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_arrows_style" AS ENUM('default', 'minimal', 'square', 'hover-only');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_arrows_position" AS ENUM('sides', 'bottom-left', 'bottom-right', 'bottom-center');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_dots_style" AS ENUM('dots', 'lines', 'numbers', 'thumbnails', 'progress');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_dots_position" AS ENUM('bottom-center', 'bottom-left', 'bottom-right', 'left', 'right');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_dots_color" AS ENUM('white', 'dark', 'primary');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_layout_height" AS ENUM('viewport', 'large', 'medium', 'small', 'compact', 'auto');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_layout_mobile_height" AS ENUM('same', 'viewport', 'large', 'medium', 'small', 'compact');
CREATE TYPE "public"."enum_pages_blocks_hero_slider_block_layout_content_width" AS ENUM('container', 'narrow', 'wide', 'full');
CREATE TABLE "pages_blocks_hero_slider_block_slides" (
"_order" integer NOT NULL,
"_parent_id" varchar NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"background_image_id" integer NOT NULL,
"mobile_background_image_id" integer,
"text_alignment" "enum_pages_blocks_hero_slider_block_slides_text_alignment" DEFAULT 'center',
"vertical_position" "enum_pages_blocks_hero_slider_block_slides_vertical_position" DEFAULT 'center',
"overlay_enabled" boolean DEFAULT true,
"overlay_color" "enum_pages_blocks_hero_slider_block_slides_overlay_color" DEFAULT 'dark',
"overlay_opacity" "enum_pages_blocks_hero_slider_block_slides_overlay_opacity" DEFAULT '50',
"primary_cta_enabled" boolean DEFAULT true,
"primary_cta_link" varchar,
"primary_cta_style" "enum_pages_blocks_hero_slider_block_slides_primary_cta_style" DEFAULT 'primary',
"primary_cta_open_in_new_tab" boolean DEFAULT false,
"secondary_cta_enabled" boolean DEFAULT false,
"secondary_cta_link" varchar,
"secondary_cta_style" "enum_pages_blocks_hero_slider_block_slides_secondary_cta_style" DEFAULT 'outline-white',
"secondary_cta_open_in_new_tab" boolean DEFAULT false,
"text_color" "enum_pages_blocks_hero_slider_block_slides_text_color" DEFAULT 'white'
);
CREATE TABLE "pages_blocks_hero_slider_block_slides_locales" (
"headline" varchar NOT NULL,
"subline" varchar,
"primary_cta_text" varchar,
"secondary_cta_text" varchar,
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
CREATE TABLE "pages_blocks_hero_slider_block" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"_path" text NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"settings_animation" "enum_pages_blocks_hero_slider_block_settings_animation" DEFAULT 'fade',
"settings_animation_duration" "enum_pages_blocks_hero_slider_block_settings_animation_duration" DEFAULT '500',
"settings_autoplay_enabled" boolean DEFAULT true,
"settings_autoplay_interval" "enum_pages_blocks_hero_slider_block_settings_autoplay_interval" DEFAULT '5000',
"settings_autoplay_pause_on_hover" boolean DEFAULT true,
"settings_autoplay_pause_on_interaction" boolean DEFAULT true,
"settings_loop" boolean DEFAULT true,
"navigation_arrows_enabled" boolean DEFAULT true,
"navigation_arrows_style" "enum_pages_blocks_hero_slider_block_navigation_arrows_style" DEFAULT 'default',
"navigation_arrows_position" "enum_pages_blocks_hero_slider_block_navigation_arrows_position" DEFAULT 'sides',
"navigation_arrows_hide_on_mobile" boolean DEFAULT false,
"navigation_dots_enabled" boolean DEFAULT true,
"navigation_dots_style" "enum_pages_blocks_hero_slider_block_navigation_dots_style" DEFAULT 'dots',
"navigation_dots_position" "enum_pages_blocks_hero_slider_block_navigation_dots_position" DEFAULT 'bottom-center',
"navigation_dots_color" "enum_pages_blocks_hero_slider_block_navigation_dots_color" DEFAULT 'white',
"navigation_swipe" boolean DEFAULT true,
"navigation_keyboard" boolean DEFAULT true,
"layout_height" "enum_pages_blocks_hero_slider_block_layout_height" DEFAULT 'viewport',
"layout_mobile_height" "enum_pages_blocks_hero_slider_block_layout_mobile_height" DEFAULT 'viewport',
"layout_content_width" "enum_pages_blocks_hero_slider_block_layout_content_width" DEFAULT 'container',
"layout_full_width" boolean DEFAULT true,
"accessibility_reduced_motion" boolean DEFAULT true,
"block_name" varchar
);
CREATE TABLE "pages_blocks_hero_slider_block_locales" (
"accessibility_aria_label" varchar DEFAULT 'Hero Slider',
"id" serial PRIMARY KEY NOT NULL,
"_locale" "_locales" NOT NULL,
"_parent_id" varchar NOT NULL
);
ALTER TABLE "pages_blocks_hero_slider_block_slides" ADD CONSTRAINT "pages_blocks_hero_slider_block_slides_background_image_id_media_id_fk" FOREIGN KEY ("background_image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
ALTER TABLE "pages_blocks_hero_slider_block_slides" ADD CONSTRAINT "pages_blocks_hero_slider_block_slides_mobile_background_image_id_media_id_fk" FOREIGN KEY ("mobile_background_image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
ALTER TABLE "pages_blocks_hero_slider_block_slides" ADD CONSTRAINT "pages_blocks_hero_slider_block_slides_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_hero_slider_block"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_hero_slider_block_slides_locales" ADD CONSTRAINT "pages_blocks_hero_slider_block_slides_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_hero_slider_block_slides"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_hero_slider_block" ADD CONSTRAINT "pages_blocks_hero_slider_block_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_blocks_hero_slider_block_locales" ADD CONSTRAINT "pages_blocks_hero_slider_block_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_hero_slider_block"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "pages_blocks_hero_slider_block_slides_order_idx" ON "pages_blocks_hero_slider_block_slides" USING btree ("_order");
CREATE INDEX "pages_blocks_hero_slider_block_slides_parent_id_idx" ON "pages_blocks_hero_slider_block_slides" USING btree ("_parent_id");
CREATE INDEX "pages_blocks_hero_slider_block_slides_background_image_idx" ON "pages_blocks_hero_slider_block_slides" USING btree ("background_image_id");
CREATE INDEX "pages_blocks_hero_slider_block_slides_mobile_background__idx" ON "pages_blocks_hero_slider_block_slides" USING btree ("mobile_background_image_id");
CREATE UNIQUE INDEX "pages_blocks_hero_slider_block_slides_locales_locale_parent_" ON "pages_blocks_hero_slider_block_slides_locales" USING btree ("_locale","_parent_id");
CREATE INDEX "pages_blocks_hero_slider_block_order_idx" ON "pages_blocks_hero_slider_block" USING btree ("_order");
CREATE INDEX "pages_blocks_hero_slider_block_parent_id_idx" ON "pages_blocks_hero_slider_block" USING btree ("_parent_id");
CREATE INDEX "pages_blocks_hero_slider_block_path_idx" ON "pages_blocks_hero_slider_block" USING btree ("_path");
CREATE UNIQUE INDEX "pages_blocks_hero_slider_block_locales_locale_parent_id_uniq" ON "pages_blocks_hero_slider_block_locales" USING btree ("_locale","_parent_id");`)
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
DROP TABLE "pages_blocks_hero_slider_block_slides" CASCADE;
DROP TABLE "pages_blocks_hero_slider_block_slides_locales" CASCADE;
DROP TABLE "pages_blocks_hero_slider_block" CASCADE;
DROP TABLE "pages_blocks_hero_slider_block_locales" CASCADE;
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_slides_text_alignment";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_slides_vertical_position";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_slides_overlay_color";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_slides_overlay_opacity";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_slides_primary_cta_style";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_slides_secondary_cta_style";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_slides_text_color";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_settings_animation";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_settings_animation_duration";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_settings_autoplay_interval";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_arrows_style";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_arrows_position";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_dots_style";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_dots_position";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_navigation_dots_color";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_layout_height";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_layout_mobile_height";
DROP TYPE "public"."enum_pages_blocks_hero_slider_block_layout_content_width";`)
}

View file

@ -11,6 +11,7 @@ import * as migration_20251210_090000_enhance_form_submissions from './20251210_
import * as migration_20251212_211506_add_products_collections from './20251212_211506_add_products_collections';
import * as migration_20251213_100753_add_timelines_collection from './20251213_100753_add_timelines_collection';
import * as migration_20251213_104523_add_workflows_and_timeline_process_fields from './20251213_104523_add_workflows_and_timeline_process_fields';
import * as migration_20251213_145438_hero_slider_block from './20251213_145438_hero_slider_block';
export const migrations = [
{
@ -76,6 +77,11 @@ export const migrations = [
{
up: migration_20251213_104523_add_workflows_and_timeline_process_fields.up,
down: migration_20251213_104523_add_workflows_and_timeline_process_fields.down,
name: '20251213_104523_add_workflows_and_timeline_process_fields'
name: '20251213_104523_add_workflows_and_timeline_process_fields',
},
{
up: migration_20251213_145438_hero_slider_block.up,
down: migration_20251213_145438_hero_slider_block.down,
name: '20251213_145438_hero_slider_block'
},
];

View file

@ -420,6 +420,122 @@ export interface Page {
blockName?: string | null;
blockType: 'hero-block';
}
| {
/**
* Mindestens 1 Slide erforderlich, maximal 10 Slides
*/
slides: {
/**
* Empfohlen: 1920x1080px oder größer
*/
backgroundImage: number | Media;
/**
* Optional: Alternatives Bild für mobile Geräte (Portrait-Format empfohlen)
*/
mobileBackgroundImage?: (number | null) | Media;
/**
* Hauptüberschrift des Slides
*/
headline: string;
/**
* Optionaler Untertitel oder kurze Beschreibung
*/
subline?: string | null;
textAlignment?: ('left' | 'center' | 'right') | null;
verticalPosition?: ('top' | 'center' | 'bottom') | null;
overlay?: {
enabled?: boolean | null;
color?: ('dark' | 'light' | 'primary' | 'gradient-bottom' | 'gradient-top') | null;
opacity?: ('20' | '30' | '40' | '50' | '60' | '70' | '80') | null;
};
primaryCta?: {
enabled?: boolean | null;
text?: string | null;
/**
* URL oder interner Pfad (z.B. /kontakt)
*/
link?: string | null;
style?: ('primary' | 'secondary' | 'outline-white' | 'outline-dark') | null;
openInNewTab?: boolean | null;
};
secondaryCta?: {
enabled?: boolean | null;
text?: string | null;
link?: string | null;
style?: ('primary' | 'secondary' | 'outline-white' | 'outline-dark' | 'text') | null;
openInNewTab?: boolean | null;
};
textColor?: ('white' | 'dark' | 'primary') | null;
id?: string | null;
}[];
settings?: {
/**
* Art des Übergangs zwischen den Slides
*/
animation?: ('fade' | 'slide' | 'zoom' | 'flip' | 'none') | null;
animationDuration?: ('300' | '500' | '800' | '1200') | null;
autoplay?: {
enabled?: boolean | null;
interval?: ('3000' | '4000' | '5000' | '6000' | '7000' | '8000' | '10000') | null;
/**
* Autoplay pausiert, wenn der Mauszeiger über dem Slider ist
*/
pauseOnHover?: boolean | null;
/**
* Autoplay pausiert nach manueller Navigation
*/
pauseOnInteraction?: boolean | null;
};
/**
* Nach dem letzten Slide automatisch zum ersten springen
*/
loop?: boolean | null;
};
navigation?: {
arrows?: {
enabled?: boolean | null;
style?: ('default' | 'minimal' | 'square' | 'hover-only') | null;
position?: ('sides' | 'bottom-left' | 'bottom-right' | 'bottom-center') | null;
hideOnMobile?: boolean | null;
};
dots?: {
enabled?: boolean | null;
style?: ('dots' | 'lines' | 'numbers' | 'thumbnails' | 'progress') | null;
position?: ('bottom-center' | 'bottom-left' | 'bottom-right' | 'left' | 'right') | null;
color?: ('white' | 'dark' | 'primary') | null;
};
/**
* Ermöglicht Wischen auf Touch-Geräten
*/
swipe?: boolean | null;
/**
* Navigation mit Pfeiltasten ermöglichen
*/
keyboard?: boolean | null;
};
layout?: {
height?: ('viewport' | 'large' | 'medium' | 'small' | 'compact' | 'auto') | null;
mobileHeight?: ('same' | 'viewport' | 'large' | 'medium' | 'small' | 'compact') | null;
contentWidth?: ('container' | 'narrow' | 'wide' | 'full') | null;
/**
* Slider nimmt die volle Bildschirmbreite ein
*/
fullWidth?: boolean | null;
};
accessibility?: {
/**
* Beschreibung für Screenreader
*/
ariaLabel?: string | null;
/**
* Autoplay deaktivieren, wenn der User "prefers-reduced-motion" aktiviert hat
*/
reducedMotion?: boolean | null;
};
id?: string | null;
blockName?: string | null;
blockType: 'hero-slider-block';
}
| {
content: {
root: {
@ -3161,6 +3277,100 @@ export interface PagesSelect<T extends boolean = true> {
id?: T;
blockName?: T;
};
'hero-slider-block'?:
| T
| {
slides?:
| T
| {
backgroundImage?: T;
mobileBackgroundImage?: T;
headline?: T;
subline?: T;
textAlignment?: T;
verticalPosition?: T;
overlay?:
| T
| {
enabled?: T;
color?: T;
opacity?: T;
};
primaryCta?:
| T
| {
enabled?: T;
text?: T;
link?: T;
style?: T;
openInNewTab?: T;
};
secondaryCta?:
| T
| {
enabled?: T;
text?: T;
link?: T;
style?: T;
openInNewTab?: T;
};
textColor?: T;
id?: T;
};
settings?:
| T
| {
animation?: T;
animationDuration?: T;
autoplay?:
| T
| {
enabled?: T;
interval?: T;
pauseOnHover?: T;
pauseOnInteraction?: T;
};
loop?: T;
};
navigation?:
| T
| {
arrows?:
| T
| {
enabled?: T;
style?: T;
position?: T;
hideOnMobile?: T;
};
dots?:
| T
| {
enabled?: T;
style?: T;
position?: T;
color?: T;
};
swipe?: T;
keyboard?: T;
};
layout?:
| T
| {
height?: T;
mobileHeight?: T;
contentWidth?: T;
fullWidth?: T;
};
accessibility?:
| T
| {
ariaLabel?: T;
reducedMotion?: T;
};
id?: T;
blockName?: T;
};
'text-block'?:
| T
| {