mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 18:34:13 +00:00
feat: add ImageSliderBlock for image galleries and sliders
Layouts: - Slider, Grid, Masonry, Single, Thumbnails, Filmstrip Images Array (1-50): - Upload with caption, alt text, optional link - Localized captions Slider Options: - Effects: slide, fade, zoom, flip, coverflow, cube - Speed, slides per view, gap, autoplay, loop, centered Navigation: - Arrows with 4 styles - Dots with 4 styles (dots, lines, numbers, progress) - Counter, swipe, keyboard support Lightbox: - Zoom, download, share buttons - Captions, thumbnails - Background styles (dark, light, blur) Styling: - Height options (auto to fullscreen) - Image fit, rounded corners, shadows, borders - Hover effects (zoom, brighten, darken, overlay) - Caption positions (below, overlay, hover, hidden) - Background and padding options 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8116180955
commit
f0424a4abf
5 changed files with 934 additions and 0 deletions
549
src/blocks/ImageSliderBlock.ts
Normal file
549
src/blocks/ImageSliderBlock.ts
Normal file
|
|
@ -0,0 +1,549 @@
|
|||
import type { Block } from 'payload'
|
||||
|
||||
/**
|
||||
* ImageSliderBlock / GalleryBlock
|
||||
*
|
||||
* Vielseitiger Bild-Slider und Galerie-Block mit:
|
||||
* - Mehreren Layouts (Slider, Grid, Masonry)
|
||||
* - Lightbox-Funktion
|
||||
* - Thumbnail-Navigation
|
||||
* - Bildunterschriften
|
||||
* - Verschiedenen Animationen
|
||||
*/
|
||||
export const ImageSliderBlock: Block = {
|
||||
slug: 'image-slider-block',
|
||||
labels: {
|
||||
singular: 'Bildergalerie',
|
||||
plural: 'Bildergalerien',
|
||||
},
|
||||
imageURL: '/assets/blocks/image-slider.png',
|
||||
fields: [
|
||||
// Titel & Beschreibung
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
label: 'Titel',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Optionaler Titel über der Galerie',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
type: 'textarea',
|
||||
label: 'Beschreibung',
|
||||
localized: true,
|
||||
},
|
||||
|
||||
// Bilder Array
|
||||
{
|
||||
name: 'images',
|
||||
type: 'array',
|
||||
required: true,
|
||||
minRows: 1,
|
||||
maxRows: 50,
|
||||
label: 'Bilder',
|
||||
labels: {
|
||||
singular: 'Bild',
|
||||
plural: 'Bilder',
|
||||
},
|
||||
admin: {
|
||||
description: 'Mindestens 1 Bild, maximal 50 Bilder',
|
||||
initCollapsed: false,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'image',
|
||||
type: 'upload',
|
||||
relationTo: 'media',
|
||||
required: true,
|
||||
label: 'Bild',
|
||||
},
|
||||
{
|
||||
name: 'caption',
|
||||
type: 'text',
|
||||
label: 'Bildunterschrift',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'alt',
|
||||
type: 'text',
|
||||
label: 'Alt-Text',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Alternativer Text für Barrierefreiheit (falls abweichend vom Media Alt)',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'link',
|
||||
type: 'text',
|
||||
label: 'Link',
|
||||
admin: {
|
||||
description: 'Optionaler Link beim Klick (statt Lightbox)',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Layout
|
||||
{
|
||||
name: 'layout',
|
||||
type: 'select',
|
||||
defaultValue: 'slider',
|
||||
label: 'Layout',
|
||||
options: [
|
||||
{ label: 'Slider', value: 'slider' },
|
||||
{ label: 'Grid', value: 'grid' },
|
||||
{ label: 'Masonry', value: 'masonry' },
|
||||
{ label: 'Einzelbild (Featured)', value: 'single' },
|
||||
{ label: 'Thumbnails unten', value: 'thumbs' },
|
||||
{ label: 'Filmstreifen', value: 'filmstrip' },
|
||||
],
|
||||
},
|
||||
|
||||
// Grid/Masonry Optionen
|
||||
{
|
||||
name: 'grid',
|
||||
type: 'group',
|
||||
label: 'Grid-Einstellungen',
|
||||
admin: {
|
||||
condition: (_, siblingData) =>
|
||||
siblingData?.layout === 'grid' || siblingData?.layout === 'masonry',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'cols',
|
||||
type: 'select',
|
||||
defaultValue: '3',
|
||||
label: 'Spalten',
|
||||
options: [
|
||||
{ label: '2 Spalten', value: '2' },
|
||||
{ label: '3 Spalten', value: '3' },
|
||||
{ label: '4 Spalten', value: '4' },
|
||||
{ label: '5 Spalten', value: '5' },
|
||||
{ label: '6 Spalten', value: '6' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'gap',
|
||||
type: 'select',
|
||||
defaultValue: '16',
|
||||
label: 'Abstand',
|
||||
options: [
|
||||
{ label: 'Kein Abstand', value: '0' },
|
||||
{ label: 'Klein (8px)', value: '8' },
|
||||
{ label: 'Normal (16px)', value: '16' },
|
||||
{ label: 'Groß (24px)', value: '24' },
|
||||
{ label: 'Sehr groß (32px)', value: '32' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'aspectRatio',
|
||||
type: 'select',
|
||||
defaultValue: 'square',
|
||||
label: 'Seitenverhältnis',
|
||||
options: [
|
||||
{ label: 'Quadratisch (1:1)', value: 'square' },
|
||||
{ label: 'Querformat (4:3)', value: '4-3' },
|
||||
{ label: 'Breit (16:9)', value: '16-9' },
|
||||
{ label: 'Hochformat (3:4)', value: '3-4' },
|
||||
{ label: 'Original', value: 'auto' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.layout !== 'masonry',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Slider-Einstellungen
|
||||
{
|
||||
name: 'slider',
|
||||
type: 'group',
|
||||
label: 'Slider-Einstellungen',
|
||||
admin: {
|
||||
condition: (_, siblingData) =>
|
||||
siblingData?.layout === 'slider' ||
|
||||
siblingData?.layout === 'thumbs' ||
|
||||
siblingData?.layout === 'filmstrip',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'effect',
|
||||
type: 'select',
|
||||
defaultValue: 'slide',
|
||||
label: 'Animation',
|
||||
options: [
|
||||
{ label: 'Schieben (Slide)', value: 'slide' },
|
||||
{ label: 'Überblenden (Fade)', value: 'fade' },
|
||||
{ label: 'Zoom', value: 'zoom' },
|
||||
{ label: 'Flip', value: 'flip' },
|
||||
{ label: 'Coverflow', value: 'coverflow' },
|
||||
{ label: 'Cube', value: 'cube' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'speed',
|
||||
type: 'select',
|
||||
defaultValue: '500',
|
||||
label: 'Geschwindigkeit',
|
||||
options: [
|
||||
{ label: 'Schnell (300ms)', value: '300' },
|
||||
{ label: 'Normal (500ms)', value: '500' },
|
||||
{ label: 'Langsam (800ms)', value: '800' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'perView',
|
||||
type: 'select',
|
||||
defaultValue: '1',
|
||||
label: 'Sichtbare Bilder',
|
||||
options: [
|
||||
{ label: '1', value: '1' },
|
||||
{ label: '2', value: '2' },
|
||||
{ label: '3', value: '3' },
|
||||
{ label: '4', value: '4' },
|
||||
{ label: 'Auto', value: 'auto' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'gap',
|
||||
type: 'select',
|
||||
defaultValue: '0',
|
||||
label: 'Abstand',
|
||||
options: [
|
||||
{ label: 'Kein Abstand', value: '0' },
|
||||
{ label: 'Klein (8px)', value: '8' },
|
||||
{ label: 'Normal (16px)', value: '16' },
|
||||
{ label: 'Groß (24px)', value: '24' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'auto',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Autoplay',
|
||||
},
|
||||
{
|
||||
name: 'delay',
|
||||
type: 'select',
|
||||
defaultValue: '4000',
|
||||
label: 'Intervall',
|
||||
options: [
|
||||
{ label: '3 Sekunden', value: '3000' },
|
||||
{ label: '4 Sekunden', value: '4000' },
|
||||
{ label: '5 Sekunden', value: '5000' },
|
||||
{ label: '6 Sekunden', value: '6000' },
|
||||
{ label: '8 Sekunden', value: '8000' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.auto,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'pauseHover',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Bei Hover pausieren',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.auto,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'loop',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Endlosschleife',
|
||||
},
|
||||
{
|
||||
name: 'centered',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Aktives Bild zentrieren',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Navigation
|
||||
{
|
||||
name: 'nav',
|
||||
type: 'group',
|
||||
label: 'Navigation',
|
||||
admin: {
|
||||
condition: (_, siblingData) =>
|
||||
siblingData?.layout === 'slider' ||
|
||||
siblingData?.layout === 'thumbs' ||
|
||||
siblingData?.layout === 'filmstrip',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'arrows',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Pfeile anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'arrowStyle',
|
||||
type: 'select',
|
||||
defaultValue: 'default',
|
||||
label: 'Pfeil-Stil',
|
||||
options: [
|
||||
{ label: 'Standard', value: 'default' },
|
||||
{ label: 'Minimal', value: 'minimal' },
|
||||
{ label: 'Eckig', value: 'square' },
|
||||
{ label: 'Nur bei Hover', value: 'hover' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.arrows,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'dots',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Punkte anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'dotStyle',
|
||||
type: 'select',
|
||||
defaultValue: 'dots',
|
||||
label: 'Punkte-Stil',
|
||||
options: [
|
||||
{ label: 'Punkte', value: 'dots' },
|
||||
{ label: 'Striche', value: 'lines' },
|
||||
{ label: 'Nummern', value: 'numbers' },
|
||||
{ label: 'Fortschritt', value: 'progress' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.dots,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'counter',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Zähler anzeigen (1/10)',
|
||||
},
|
||||
{
|
||||
name: 'swipe',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Touch-Swipe',
|
||||
},
|
||||
{
|
||||
name: 'keys',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Tastaturnavigation',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Lightbox
|
||||
{
|
||||
name: 'lightbox',
|
||||
type: 'group',
|
||||
label: 'Lightbox',
|
||||
fields: [
|
||||
{
|
||||
name: 'enabled',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Lightbox aktivieren',
|
||||
admin: {
|
||||
description: 'Bilder bei Klick in Vollansicht öffnen',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'zoom',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Zoom erlauben',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.enabled,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'download',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Download-Button',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.enabled,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'share',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Teilen-Button',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.enabled,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'captions',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Bildunterschriften anzeigen',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.enabled,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'thumbs',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Thumbnails anzeigen',
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.enabled,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'bg',
|
||||
type: 'select',
|
||||
defaultValue: 'dark',
|
||||
label: 'Hintergrund',
|
||||
options: [
|
||||
{ label: 'Dunkel', value: 'dark' },
|
||||
{ label: 'Hell', value: 'light' },
|
||||
{ label: 'Blur', value: 'blur' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => siblingData?.enabled,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Darstellung
|
||||
{
|
||||
name: 'style',
|
||||
type: 'group',
|
||||
label: 'Darstellung',
|
||||
fields: [
|
||||
{
|
||||
name: 'height',
|
||||
type: 'select',
|
||||
defaultValue: 'auto',
|
||||
label: 'Höhe',
|
||||
options: [
|
||||
{ label: 'Auto (Bildverhältnis)', value: 'auto' },
|
||||
{ label: 'Klein (300px)', value: '300' },
|
||||
{ label: 'Mittel (400px)', value: '400' },
|
||||
{ label: 'Groß (500px)', value: '500' },
|
||||
{ label: 'Sehr groß (600px)', value: '600' },
|
||||
{ label: 'Vollbild (100vh)', value: 'full' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'imgFit',
|
||||
type: 'select',
|
||||
defaultValue: 'cover',
|
||||
label: 'Bildanpassung',
|
||||
options: [
|
||||
{ label: 'Ausfüllen (cover)', value: 'cover' },
|
||||
{ label: 'Einpassen (contain)', value: 'contain' },
|
||||
{ label: 'Strecken (fill)', value: 'fill' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'rounded',
|
||||
type: 'select',
|
||||
defaultValue: 'none',
|
||||
label: 'Ecken',
|
||||
options: [
|
||||
{ label: 'Keine', value: 'none' },
|
||||
{ label: 'Klein', value: 'sm' },
|
||||
{ label: 'Mittel', value: 'md' },
|
||||
{ label: 'Groß', value: 'lg' },
|
||||
{ label: 'Rund', value: 'full' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'shadow',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Schatten',
|
||||
},
|
||||
{
|
||||
name: 'border',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Rahmen',
|
||||
},
|
||||
{
|
||||
name: 'hoverEffect',
|
||||
type: 'select',
|
||||
defaultValue: 'none',
|
||||
label: 'Hover-Effekt',
|
||||
options: [
|
||||
{ label: 'Keiner', value: 'none' },
|
||||
{ label: 'Zoom', value: 'zoom' },
|
||||
{ label: 'Aufhellen', value: 'brighten' },
|
||||
{ label: 'Abdunkeln', value: 'darken' },
|
||||
{ label: 'Overlay', value: 'overlay' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'captionPos',
|
||||
type: 'select',
|
||||
defaultValue: 'below',
|
||||
label: 'Bildunterschrift-Position',
|
||||
options: [
|
||||
{ label: 'Unterhalb', value: 'below' },
|
||||
{ label: 'Overlay unten', value: 'overlay' },
|
||||
{ label: 'Bei Hover', value: 'hover' },
|
||||
{ label: 'Versteckt', value: 'hidden' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'bg',
|
||||
type: 'select',
|
||||
defaultValue: 'none',
|
||||
label: 'Hintergrund',
|
||||
options: [
|
||||
{ label: 'Keiner', value: 'none' },
|
||||
{ label: 'Weiß', value: 'white' },
|
||||
{ label: 'Grau', value: 'light' },
|
||||
{ label: 'Dunkel', value: 'dark' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'padding',
|
||||
type: 'select',
|
||||
defaultValue: 'none',
|
||||
label: 'Außenabstand',
|
||||
options: [
|
||||
{ label: 'Keiner', value: 'none' },
|
||||
{ label: 'Klein', value: 'sm' },
|
||||
{ label: 'Normal', value: 'md' },
|
||||
{ label: 'Groß', value: 'lg' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Accessibility
|
||||
{
|
||||
name: 'a11y',
|
||||
type: 'group',
|
||||
label: 'Barrierefreiheit',
|
||||
fields: [
|
||||
{
|
||||
name: 'label',
|
||||
type: 'text',
|
||||
defaultValue: 'Bildergalerie',
|
||||
label: 'ARIA Label',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'reducedMotion',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Reduzierte Bewegung respektieren',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
export { HeroBlock } from './HeroBlock'
|
||||
export { HeroSliderBlock } from './HeroSliderBlock'
|
||||
export { ImageSliderBlock } from './ImageSliderBlock'
|
||||
export { TextBlock } from './TextBlock'
|
||||
export { ImageTextBlock } from './ImageTextBlock'
|
||||
export { CardGridBlock } from './CardGridBlock'
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import type { CollectionConfig } from 'payload'
|
|||
import {
|
||||
HeroBlock,
|
||||
HeroSliderBlock,
|
||||
ImageSliderBlock,
|
||||
TextBlock,
|
||||
ImageTextBlock,
|
||||
CardGridBlock,
|
||||
|
|
@ -75,6 +76,7 @@ export const Pages: CollectionConfig = {
|
|||
// Bestehende Blocks
|
||||
HeroBlock,
|
||||
HeroSliderBlock,
|
||||
ImageSliderBlock,
|
||||
TextBlock,
|
||||
ImageTextBlock,
|
||||
CardGridBlock,
|
||||
|
|
|
|||
224
src/migrations/20251213_210000_image_slider_block.ts
Normal file
224
src/migrations/20251213_210000_image_slider_block.ts
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||
|
||||
/**
|
||||
* Migration: ImageSliderBlock
|
||||
*
|
||||
* Erstellt den ImageSliderBlock für Bildergalerien mit:
|
||||
* - Verschiedenen Layouts (Slider, Grid, Masonry)
|
||||
* - Lightbox-Funktion
|
||||
* - Flexible Slider-Optionen
|
||||
* - Styling und Navigation
|
||||
*/
|
||||
|
||||
export async function up({ db }: MigrateUpArgs): Promise<void> {
|
||||
// Create enums
|
||||
await db.execute(sql`
|
||||
-- Layout
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_layout" AS ENUM('slider', 'grid', 'masonry', 'single', 'thumbs', 'filmstrip');
|
||||
|
||||
-- Grid
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_grid_cols" AS ENUM('2', '3', '4', '5', '6');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_grid_gap" AS ENUM('0', '8', '16', '24', '32');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_grid_aspect" AS ENUM('square', '4-3', '16-9', '3-4', 'auto');
|
||||
|
||||
-- Slider
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_slider_effect" AS ENUM('slide', 'fade', 'zoom', 'flip', 'coverflow', 'cube');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_slider_speed" AS ENUM('300', '500', '800');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_slider_per_view" AS ENUM('1', '2', '3', '4', 'auto');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_slider_gap" AS ENUM('0', '8', '16', '24');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_slider_delay" AS ENUM('3000', '4000', '5000', '6000', '8000');
|
||||
|
||||
-- Navigation
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_nav_arrow_style" AS ENUM('default', 'minimal', 'square', 'hover');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_nav_dot_style" AS ENUM('dots', 'lines', 'numbers', 'progress');
|
||||
|
||||
-- Lightbox
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_lightbox_bg" AS ENUM('dark', 'light', 'blur');
|
||||
|
||||
-- Style
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_style_height" AS ENUM('auto', '300', '400', '500', '600', 'full');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_style_img_fit" AS ENUM('cover', 'contain', 'fill');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_style_rounded" AS ENUM('none', 'sm', 'md', 'lg', 'full');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_style_hover" AS ENUM('none', 'zoom', 'brighten', 'darken', 'overlay');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_style_caption" AS ENUM('below', 'overlay', 'hover', 'hidden');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_style_bg" AS ENUM('none', 'white', 'light', 'dark');
|
||||
CREATE TYPE "enum_pages_blocks_image_slider_block_style_padding" AS ENUM('none', 'sm', 'md', 'lg');
|
||||
`)
|
||||
|
||||
// Create images array table
|
||||
await db.execute(sql`
|
||||
CREATE TABLE "pages_blocks_image_slider_block_images" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" varchar NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL,
|
||||
"image_id" integer NOT NULL,
|
||||
"link" varchar
|
||||
);
|
||||
`)
|
||||
|
||||
// Create images locales table
|
||||
await db.execute(sql`
|
||||
CREATE TABLE "pages_blocks_image_slider_block_images_locales" (
|
||||
"caption" varchar,
|
||||
"alt" varchar,
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
`)
|
||||
|
||||
// Create main block table
|
||||
await db.execute(sql`
|
||||
CREATE TABLE "pages_blocks_image_slider_block" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" integer NOT NULL,
|
||||
"_path" text NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL,
|
||||
|
||||
-- Layout
|
||||
"layout" "enum_pages_blocks_image_slider_block_layout" DEFAULT 'slider',
|
||||
|
||||
-- Grid settings
|
||||
"grid_cols" "enum_pages_blocks_image_slider_block_grid_cols" DEFAULT '3',
|
||||
"grid_gap" "enum_pages_blocks_image_slider_block_grid_gap" DEFAULT '16',
|
||||
"grid_aspect_ratio" "enum_pages_blocks_image_slider_block_grid_aspect" DEFAULT 'square',
|
||||
|
||||
-- Slider settings
|
||||
"slider_effect" "enum_pages_blocks_image_slider_block_slider_effect" DEFAULT 'slide',
|
||||
"slider_speed" "enum_pages_blocks_image_slider_block_slider_speed" DEFAULT '500',
|
||||
"slider_per_view" "enum_pages_blocks_image_slider_block_slider_per_view" DEFAULT '1',
|
||||
"slider_gap" "enum_pages_blocks_image_slider_block_slider_gap" DEFAULT '0',
|
||||
"slider_auto" boolean DEFAULT false,
|
||||
"slider_delay" "enum_pages_blocks_image_slider_block_slider_delay" DEFAULT '4000',
|
||||
"slider_pause_hover" boolean DEFAULT true,
|
||||
"slider_loop" boolean DEFAULT true,
|
||||
"slider_centered" boolean DEFAULT false,
|
||||
|
||||
-- Navigation
|
||||
"nav_arrows" boolean DEFAULT true,
|
||||
"nav_arrow_style" "enum_pages_blocks_image_slider_block_nav_arrow_style" DEFAULT 'default',
|
||||
"nav_dots" boolean DEFAULT true,
|
||||
"nav_dot_style" "enum_pages_blocks_image_slider_block_nav_dot_style" DEFAULT 'dots',
|
||||
"nav_counter" boolean DEFAULT false,
|
||||
"nav_swipe" boolean DEFAULT true,
|
||||
"nav_keys" boolean DEFAULT true,
|
||||
|
||||
-- Lightbox
|
||||
"lightbox_enabled" boolean DEFAULT true,
|
||||
"lightbox_zoom" boolean DEFAULT true,
|
||||
"lightbox_download" boolean DEFAULT false,
|
||||
"lightbox_share" boolean DEFAULT false,
|
||||
"lightbox_captions" boolean DEFAULT true,
|
||||
"lightbox_thumbs" boolean DEFAULT true,
|
||||
"lightbox_bg" "enum_pages_blocks_image_slider_block_lightbox_bg" DEFAULT 'dark',
|
||||
|
||||
-- Style
|
||||
"style_height" "enum_pages_blocks_image_slider_block_style_height" DEFAULT 'auto',
|
||||
"style_img_fit" "enum_pages_blocks_image_slider_block_style_img_fit" DEFAULT 'cover',
|
||||
"style_rounded" "enum_pages_blocks_image_slider_block_style_rounded" DEFAULT 'none',
|
||||
"style_shadow" boolean DEFAULT false,
|
||||
"style_border" boolean DEFAULT false,
|
||||
"style_hover_effect" "enum_pages_blocks_image_slider_block_style_hover" DEFAULT 'none',
|
||||
"style_caption_pos" "enum_pages_blocks_image_slider_block_style_caption" DEFAULT 'below',
|
||||
"style_bg" "enum_pages_blocks_image_slider_block_style_bg" DEFAULT 'none',
|
||||
"style_padding" "enum_pages_blocks_image_slider_block_style_padding" DEFAULT 'none',
|
||||
|
||||
-- Accessibility
|
||||
"a11y_reduced_motion" boolean DEFAULT true,
|
||||
|
||||
"block_name" varchar
|
||||
);
|
||||
`)
|
||||
|
||||
// Create locales table
|
||||
await db.execute(sql`
|
||||
CREATE TABLE "pages_blocks_image_slider_block_locales" (
|
||||
"title" varchar,
|
||||
"description" varchar,
|
||||
"a11y_label" varchar DEFAULT 'Bildergalerie',
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
`)
|
||||
|
||||
// Add foreign keys and indexes
|
||||
await db.execute(sql`
|
||||
-- Images table
|
||||
ALTER TABLE "pages_blocks_image_slider_block_images"
|
||||
ADD CONSTRAINT "pages_blocks_image_slider_block_images_image_id_fk"
|
||||
FOREIGN KEY ("image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||
|
||||
ALTER TABLE "pages_blocks_image_slider_block_images"
|
||||
ADD CONSTRAINT "pages_blocks_image_slider_block_images_parent_id_fk"
|
||||
FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_image_slider_block"("id") ON DELETE cascade ON UPDATE no action;
|
||||
|
||||
CREATE INDEX "pages_blocks_image_slider_block_images_order_idx"
|
||||
ON "pages_blocks_image_slider_block_images" USING btree ("_order");
|
||||
CREATE INDEX "pages_blocks_image_slider_block_images_parent_id_idx"
|
||||
ON "pages_blocks_image_slider_block_images" USING btree ("_parent_id");
|
||||
CREATE INDEX "pages_blocks_image_slider_block_images_image_idx"
|
||||
ON "pages_blocks_image_slider_block_images" USING btree ("image_id");
|
||||
|
||||
-- Images locales table
|
||||
ALTER TABLE "pages_blocks_image_slider_block_images_locales"
|
||||
ADD CONSTRAINT "pages_blocks_image_slider_block_images_locales_parent_fk"
|
||||
FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_image_slider_block_images"("id") ON DELETE cascade ON UPDATE no action;
|
||||
|
||||
CREATE UNIQUE INDEX "pages_blocks_image_slider_block_images_locales_uniq"
|
||||
ON "pages_blocks_image_slider_block_images_locales" USING btree ("_locale", "_parent_id");
|
||||
|
||||
-- Main block table
|
||||
ALTER TABLE "pages_blocks_image_slider_block"
|
||||
ADD CONSTRAINT "pages_blocks_image_slider_block_parent_id_fk"
|
||||
FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
|
||||
|
||||
CREATE INDEX "pages_blocks_image_slider_block_order_idx"
|
||||
ON "pages_blocks_image_slider_block" USING btree ("_order");
|
||||
CREATE INDEX "pages_blocks_image_slider_block_parent_id_idx"
|
||||
ON "pages_blocks_image_slider_block" USING btree ("_parent_id");
|
||||
CREATE INDEX "pages_blocks_image_slider_block_path_idx"
|
||||
ON "pages_blocks_image_slider_block" USING btree ("_path");
|
||||
|
||||
-- Locales table
|
||||
ALTER TABLE "pages_blocks_image_slider_block_locales"
|
||||
ADD CONSTRAINT "pages_blocks_image_slider_block_locales_parent_id_fk"
|
||||
FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_image_slider_block"("id") ON DELETE cascade ON UPDATE no action;
|
||||
|
||||
CREATE UNIQUE INDEX "pages_blocks_image_slider_block_locales_locale_parent_uniq"
|
||||
ON "pages_blocks_image_slider_block_locales" USING btree ("_locale", "_parent_id");
|
||||
`)
|
||||
}
|
||||
|
||||
export async function down({ db }: MigrateDownArgs): Promise<void> {
|
||||
// Drop tables
|
||||
await db.execute(sql`
|
||||
DROP TABLE IF EXISTS "pages_blocks_image_slider_block_images_locales" CASCADE;
|
||||
DROP TABLE IF EXISTS "pages_blocks_image_slider_block_images" CASCADE;
|
||||
DROP TABLE IF EXISTS "pages_blocks_image_slider_block_locales" CASCADE;
|
||||
DROP TABLE IF EXISTS "pages_blocks_image_slider_block" CASCADE;
|
||||
`)
|
||||
|
||||
// Drop enums
|
||||
await db.execute(sql`
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_layout";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_grid_cols";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_grid_gap";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_grid_aspect";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_slider_effect";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_slider_speed";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_slider_per_view";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_slider_gap";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_slider_delay";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_nav_arrow_style";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_nav_dot_style";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_lightbox_bg";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_style_height";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_style_img_fit";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_style_rounded";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_style_hover";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_style_caption";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_style_bg";
|
||||
DROP TYPE IF EXISTS "enum_pages_blocks_image_slider_block_style_padding";
|
||||
`)
|
||||
}
|
||||
|
|
@ -536,6 +536,85 @@ export interface Page {
|
|||
blockName?: string | null;
|
||||
blockType: 'hero-slider-block';
|
||||
}
|
||||
| {
|
||||
/**
|
||||
* Optionaler Titel über der Galerie
|
||||
*/
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
/**
|
||||
* Mindestens 1 Bild, maximal 50 Bilder
|
||||
*/
|
||||
images: {
|
||||
image: number | Media;
|
||||
caption?: string | null;
|
||||
/**
|
||||
* Alternativer Text für Barrierefreiheit (falls abweichend vom Media Alt)
|
||||
*/
|
||||
alt?: string | null;
|
||||
/**
|
||||
* Optionaler Link beim Klick (statt Lightbox)
|
||||
*/
|
||||
link?: string | null;
|
||||
id?: string | null;
|
||||
}[];
|
||||
layout?: ('slider' | 'grid' | 'masonry' | 'single' | 'thumbs' | 'filmstrip') | null;
|
||||
grid?: {
|
||||
cols?: ('2' | '3' | '4' | '5' | '6') | null;
|
||||
gap?: ('0' | '8' | '16' | '24' | '32') | null;
|
||||
aspectRatio?: ('square' | '4-3' | '16-9' | '3-4' | 'auto') | null;
|
||||
};
|
||||
slider?: {
|
||||
effect?: ('slide' | 'fade' | 'zoom' | 'flip' | 'coverflow' | 'cube') | null;
|
||||
speed?: ('300' | '500' | '800') | null;
|
||||
perView?: ('1' | '2' | '3' | '4' | 'auto') | null;
|
||||
gap?: ('0' | '8' | '16' | '24') | null;
|
||||
auto?: boolean | null;
|
||||
delay?: ('3000' | '4000' | '5000' | '6000' | '8000') | null;
|
||||
pauseHover?: boolean | null;
|
||||
loop?: boolean | null;
|
||||
centered?: boolean | null;
|
||||
};
|
||||
nav?: {
|
||||
arrows?: boolean | null;
|
||||
arrowStyle?: ('default' | 'minimal' | 'square' | 'hover') | null;
|
||||
dots?: boolean | null;
|
||||
dotStyle?: ('dots' | 'lines' | 'numbers' | 'progress') | null;
|
||||
counter?: boolean | null;
|
||||
swipe?: boolean | null;
|
||||
keys?: boolean | null;
|
||||
};
|
||||
lightbox?: {
|
||||
/**
|
||||
* Bilder bei Klick in Vollansicht öffnen
|
||||
*/
|
||||
enabled?: boolean | null;
|
||||
zoom?: boolean | null;
|
||||
download?: boolean | null;
|
||||
share?: boolean | null;
|
||||
captions?: boolean | null;
|
||||
thumbs?: boolean | null;
|
||||
bg?: ('dark' | 'light' | 'blur') | null;
|
||||
};
|
||||
style?: {
|
||||
height?: ('auto' | '300' | '400' | '500' | '600' | 'full') | null;
|
||||
imgFit?: ('cover' | 'contain' | 'fill') | null;
|
||||
rounded?: ('none' | 'sm' | 'md' | 'lg' | 'full') | null;
|
||||
shadow?: boolean | null;
|
||||
border?: boolean | null;
|
||||
hoverEffect?: ('none' | 'zoom' | 'brighten' | 'darken' | 'overlay') | null;
|
||||
captionPos?: ('below' | 'overlay' | 'hover' | 'hidden') | null;
|
||||
bg?: ('none' | 'white' | 'light' | 'dark') | null;
|
||||
padding?: ('none' | 'sm' | 'md' | 'lg') | null;
|
||||
};
|
||||
a11y?: {
|
||||
label?: string | null;
|
||||
reducedMotion?: boolean | null;
|
||||
};
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'image-slider-block';
|
||||
}
|
||||
| {
|
||||
content: {
|
||||
root: {
|
||||
|
|
@ -3419,6 +3498,85 @@ export interface PagesSelect<T extends boolean = true> {
|
|||
id?: T;
|
||||
blockName?: T;
|
||||
};
|
||||
'image-slider-block'?:
|
||||
| T
|
||||
| {
|
||||
title?: T;
|
||||
description?: T;
|
||||
images?:
|
||||
| T
|
||||
| {
|
||||
image?: T;
|
||||
caption?: T;
|
||||
alt?: T;
|
||||
link?: T;
|
||||
id?: T;
|
||||
};
|
||||
layout?: T;
|
||||
grid?:
|
||||
| T
|
||||
| {
|
||||
cols?: T;
|
||||
gap?: T;
|
||||
aspectRatio?: T;
|
||||
};
|
||||
slider?:
|
||||
| T
|
||||
| {
|
||||
effect?: T;
|
||||
speed?: T;
|
||||
perView?: T;
|
||||
gap?: T;
|
||||
auto?: T;
|
||||
delay?: T;
|
||||
pauseHover?: T;
|
||||
loop?: T;
|
||||
centered?: T;
|
||||
};
|
||||
nav?:
|
||||
| T
|
||||
| {
|
||||
arrows?: T;
|
||||
arrowStyle?: T;
|
||||
dots?: T;
|
||||
dotStyle?: T;
|
||||
counter?: T;
|
||||
swipe?: T;
|
||||
keys?: T;
|
||||
};
|
||||
lightbox?:
|
||||
| T
|
||||
| {
|
||||
enabled?: T;
|
||||
zoom?: T;
|
||||
download?: T;
|
||||
share?: T;
|
||||
captions?: T;
|
||||
thumbs?: T;
|
||||
bg?: T;
|
||||
};
|
||||
style?:
|
||||
| T
|
||||
| {
|
||||
height?: T;
|
||||
imgFit?: T;
|
||||
rounded?: T;
|
||||
shadow?: T;
|
||||
border?: T;
|
||||
hoverEffect?: T;
|
||||
captionPos?: T;
|
||||
bg?: T;
|
||||
padding?: T;
|
||||
};
|
||||
a11y?:
|
||||
| T
|
||||
| {
|
||||
label?: T;
|
||||
reducedMotion?: T;
|
||||
};
|
||||
id?: T;
|
||||
blockName?: T;
|
||||
};
|
||||
'text-block'?:
|
||||
| T
|
||||
| {
|
||||
|
|
|
|||
Loading…
Reference in a new issue