layouts schick gemacht und packagelimits weiter implementiert

This commit is contained in:
Codex Agent
2025-11-01 22:55:13 +01:00
parent 79b209de9a
commit 8e6c66f0db
16 changed files with 756 additions and 422 deletions

View File

@@ -1,4 +1,5 @@
import type { EventQrInviteLayout } from '../../api';
// import type { EventQrInviteLayout } from '../../api'; // Temporär deaktiviert wegen Modul-Fehler; definiere lokal falls nötig
type EventQrInviteLayout = any; // Placeholder für Typ, bis Pfad gefixt
export const CANVAS_WIDTH = 1240;
export const CANVAS_HEIGHT = 1754;
@@ -23,6 +24,8 @@ export interface LayoutElement {
y: number;
width: number;
height: number;
scaleX?: number;
scaleY?: number;
rotation?: number;
fontSize?: number;
align?: LayoutTextAlign;
@@ -46,6 +49,10 @@ type LayoutPresetElement = {
height?: PresetValue;
fontSize?: number;
align?: LayoutTextAlign;
fontFamily?: string;
lineHeight?: number;
letterSpacing?: number;
rotation?: number;
locked?: boolean;
initial?: boolean;
};
@@ -65,6 +72,8 @@ export interface LayoutElementPayload {
y: number;
width: number;
height: number;
scale_x?: number;
scale_y?: number;
rotation?: number;
font_size?: number;
align?: LayoutTextAlign;
@@ -110,10 +119,10 @@ export type QrLayoutCustomization = {
elements?: LayoutElementPayload[];
};
export const MIN_QR_SIZE = 240;
export const MAX_QR_SIZE = 720;
export const MIN_TEXT_WIDTH = 160;
export const MIN_TEXT_HEIGHT = 80;
export const MIN_QR_SIZE = 400;
export const MAX_QR_SIZE = 800;
export const MIN_TEXT_WIDTH = 250;
export const MIN_TEXT_HEIGHT = 120;
export function clamp(value: number, min: number, max: number): number {
if (Number.isNaN(value)) {
@@ -125,378 +134,322 @@ export function clamp(value: number, min: number, max: number): number {
export function clampElement(element: LayoutElement): LayoutElement {
return {
...element,
x: clamp(element.x, 0, CANVAS_WIDTH - element.width),
y: clamp(element.y, 0, CANVAS_HEIGHT - element.height),
width: clamp(element.width, 40, CANVAS_WIDTH),
height: clamp(element.height, 40, CANVAS_HEIGHT),
x: clamp(element.x, 20, CANVAS_WIDTH - element.width - 20),
y: clamp(element.y, 20, CANVAS_HEIGHT - element.height - 20),
width: clamp(element.width, 40, CANVAS_WIDTH - 40),
height: clamp(element.height, 40, CANVAS_HEIGHT - 40),
scaleX: clamp(element.scaleX ?? 1, 0.1, 5),
scaleY: clamp(element.scaleY ?? 1, 0.1, 5),
};
}
const DEFAULT_TYPE_STYLES: Record<LayoutElementType, { width: number; height: number; fontSize?: number; align?: LayoutTextAlign; locked?: boolean }> = {
headline: { width: 900, height: 240, fontSize: 82, align: 'left' },
subtitle: { width: 760, height: 170, fontSize: 40, align: 'left' },
description: { width: 920, height: 340, fontSize: 32, align: 'left' },
headline: { width: 900, height: 200, fontSize: 90, align: 'left' },
subtitle: { width: 760, height: 160, fontSize: 44, align: 'left' },
description: { width: 920, height: 320, fontSize: 36, align: 'left' },
link: { width: 520, height: 130, fontSize: 30, align: 'center' },
badge: { width: 420, height: 100, fontSize: 26, align: 'center' },
logo: { width: 320, height: 220, align: 'center' },
cta: { width: 520, height: 130, fontSize: 28, align: 'center' },
qr: { width: 640, height: 640 },
qr: { width: 500, height: 500 }, // Default QR significantly larger
text: { width: 720, height: 260, fontSize: 28, align: 'left' },
};
const DEFAULT_PRESET: LayoutPreset = [
{ id: 'badge', type: 'badge', x: 140, y: 160, width: 440, height: 100, align: 'center', fontSize: 28 },
// Basierend auf dem zentrierten, modernen "confetti-bash"-Layout
{ id: 'logo', type: 'logo', x: (c) => (c.canvasWidth - 280) / 2, y: 80, width: 280, height: 140, align: 'center' },
{ id: 'badge', type: 'badge', x: (c) => (c.canvasWidth - 520) / 2, y: 240, width: 520, height: 90, align: 'center', fontSize: 28, lineHeight: 1.4, letterSpacing: 0.5, fontFamily: 'Montserrat' },
{
id: 'headline',
type: 'headline',
x: 140,
y: 300,
width: (context) => context.canvasWidth - 280,
height: 240,
fontSize: 84,
align: 'left',
},
{
id: 'subtitle',
type: 'subtitle',
x: 140,
y: 560,
width: (context) => context.canvasWidth - 280,
height: 170,
fontSize: 42,
align: 'left',
},
{
id: 'description',
type: 'description',
x: 140,
y: 750,
width: (context) => context.canvasWidth - 280,
height: 340,
fontSize: 32,
align: 'left',
},
{
id: 'qr',
type: 'qr',
x: (context) => context.canvasWidth - Math.min(context.qrSize, 680) - 180,
y: 360,
width: (context) => Math.min(context.qrSize, 680),
height: (context) => Math.min(context.qrSize, 680),
},
{
id: 'link',
type: 'link',
x: (context) => context.canvasWidth - 540,
y: (context) => 420 + Math.min(context.qrSize, 680),
width: 520,
height: 130,
fontSize: 28,
align: 'center',
},
{
id: 'cta',
type: 'cta',
x: (context) => context.canvasWidth - 540,
y: (context) => 460 + Math.min(context.qrSize, 680) + 160,
width: 520,
height: 130,
fontSize: 30,
x: (c) => (c.canvasWidth - 1000) / 2,
y: 350,
width: 1000,
height: 220,
fontSize: 110,
align: 'center',
fontFamily: 'Playfair Display',
lineHeight: 1.3,
},
{ id: 'subtitle', type: 'subtitle', x: (c) => (c.canvasWidth - 800) / 2, y: 580, width: 800, height: 120, fontSize: 42, align: 'center', fontFamily: 'Montserrat', lineHeight: 1.4 },
{ id: 'description', type: 'description', x: (c) => (c.canvasWidth - 900) / 2, y: 720, width: 900, height: 180, fontSize: 34, align: 'center', fontFamily: 'Lora', lineHeight: 1.5 },
{ id: 'qr', type: 'qr', x: (c) => (c.canvasWidth - 500) / 2, y: 940, width: (c) => Math.min(c.qrSize, 500), height: (c) => Math.min(c.qrSize, 500) },
{ id: 'cta', type: 'cta', x: (c) => (c.canvasWidth - 600) / 2, y: (c) => 940 + Math.min(c.qrSize, 500) + 40, width: 600, height: 100, align: 'center', fontSize: 32, fontFamily: 'Montserrat', lineHeight: 1.4 },
{ id: 'link', type: 'link', x: (c) => (c.canvasWidth - 700) / 2, y: (c) => 940 + Math.min(c.qrSize, 500) + 160, width: 700, height: 80, align: 'center', fontSize: 26, fontFamily: 'Montserrat', lineHeight: 1.5 },
];
const evergreenVowsPreset: LayoutPreset = [
{ id: 'logo', type: 'logo', x: 160, y: 140, width: 340, height: 240 },
{ id: 'badge', type: 'badge', x: 540, y: 160, width: 420, height: 100, align: 'center', fontSize: 28 },
// Elegant, linksbündig mit verbesserter Balance
{ id: 'logo', type: 'logo', x: 120, y: 100, width: 300, height: 150, align: 'left' },
{ id: 'badge', type: 'badge', x: (c) => c.canvasWidth - 520 - 120, y: 125, width: 520, height: 90, align: 'right', fontSize: 28, lineHeight: 1.4, fontFamily: 'Montserrat' },
{
id: 'headline',
type: 'headline',
x: 160,
y: 360,
width: (context) => context.canvasWidth - 320,
height: 250,
fontSize: 86,
x: 120,
y: 280,
width: (context) => context.canvasWidth - 240,
height: 200,
fontSize: 95,
align: 'left',
fontFamily: 'Playfair Display',
lineHeight: 1.3,
},
{
id: 'subtitle',
type: 'subtitle',
x: 160,
y: 630,
width: (context) => context.canvasWidth - 320,
height: 180,
fontSize: 42,
x: 120,
y: 490,
width: 680,
height: 140,
fontSize: 40,
align: 'left',
fontFamily: 'Montserrat',
lineHeight: 1.4,
},
{
id: 'description',
type: 'description',
x: 160,
y: 840,
width: (context) => context.canvasWidth - 320,
height: 360,
fontSize: 34,
x: 120,
y: 640,
width: 680,
height: 220,
fontSize: 32,
align: 'left',
fontFamily: 'Lora',
lineHeight: 1.5,
},
{
id: 'qr',
type: 'qr',
x: (context) => context.canvasWidth - Math.min(context.qrSize, 640) - 200,
y: 420,
width: (context) => Math.min(context.qrSize, 640),
height: (context) => Math.min(context.qrSize, 640),
},
{
id: 'link',
type: 'link',
x: (context) => context.canvasWidth - 560,
y: (context) => 480 + Math.min(context.qrSize, 640),
width: 520,
height: 130,
align: 'center',
},
{
id: 'cta',
type: 'cta',
x: (context) => context.canvasWidth - 560,
y: (context) => 520 + Math.min(context.qrSize, 640) + 180,
width: 520,
height: 130,
align: 'center',
x: (c) => c.canvasWidth - 440 - 120,
y: 920,
width: (c) => Math.min(c.qrSize, 440),
height: (c) => Math.min(c.qrSize, 440),
},
{ id: 'cta', type: 'cta', x: (c) => c.canvasWidth - 440 - 120, y: (c) => 920 + Math.min(c.qrSize, 440) + 40, width: 440, height: 100, align: 'center', fontSize: 30, fontFamily: 'Montserrat', lineHeight: 1.4 },
{ id: 'link', type: 'link', x: (c) => c.canvasWidth - 440 - 120, y: (c) => 920 + Math.min(c.qrSize, 440) + 160, width: 440, height: 80, align: 'center', fontSize: 24, fontFamily: 'Montserrat' },
];
const midnightGalaPreset: LayoutPreset = [
{ id: 'badge', type: 'badge', x: (context) => context.canvasWidth / 2 - 300, y: 180, width: 600, height: 120, align: 'center', fontSize: 32 },
// Zentriert, premium, mehr vertikaler Abstand
{ id: 'badge', type: 'badge', x: (c) => (c.canvasWidth - 560) / 2, y: 120, width: 560, height: 90, align: 'center', fontSize: 28, fontFamily: 'Montserrat' },
{
id: 'headline',
type: 'headline',
x: (context) => context.canvasWidth / 2 - (context.canvasWidth - 220) / 2,
y: 340,
width: (context) => context.canvasWidth - 220,
height: 260,
fontSize: 90,
align: 'center',
},
{
id: 'subtitle',
type: 'subtitle',
x: (context) => context.canvasWidth / 2 - (context.canvasWidth - 320) / 2,
y: 640,
width: (context) => context.canvasWidth - 320,
height: 200,
fontSize: 46,
x: (c) => (c.canvasWidth - 1100) / 2,
y: 240,
width: 1100,
height: 220,
fontSize: 105,
align: 'center',
fontFamily: 'Playfair Display',
lineHeight: 1.3,
},
{ id: 'subtitle', type: 'subtitle', x: (c) => (c.canvasWidth - 900) / 2, y: 480, width: 900, height: 120, fontSize: 40, align: 'center', fontFamily: 'Montserrat', lineHeight: 1.4 },
{ id: 'description', type: 'description', x: (c) => (c.canvasWidth - 900) / 2, y: 620, width: 900, height: 180, fontSize: 32, align: 'center', fontFamily: 'Lora', lineHeight: 1.5 },
{
id: 'qr',
type: 'qr',
x: (context) => (context.canvasWidth - Math.min(context.qrSize, 640)) / 2,
x: (c) => (c.canvasWidth - 480) / 2,
y: 880,
width: (context) => Math.min(context.qrSize, 640),
height: (context) => Math.min(context.qrSize, 640),
},
{
id: 'link',
type: 'link',
x: (context) => (context.canvasWidth - 560) / 2,
y: (context) => 940 + Math.min(context.qrSize, 640),
width: 560,
height: 140,
align: 'center',
},
{
id: 'cta',
type: 'cta',
x: (context) => (context.canvasWidth - 560) / 2,
y: (context) => 980 + Math.min(context.qrSize, 640) + 200,
width: 560,
height: 140,
align: 'center',
},
{
id: 'description',
type: 'description',
x: (context) => context.canvasWidth / 2 - (context.canvasWidth - 240) / 2,
y: 1250,
width: (context) => context.canvasWidth - 240,
height: 360,
fontSize: 34,
align: 'center',
width: (c) => Math.min(c.qrSize, 480),
height: (c) => Math.min(c.qrSize, 480),
},
{ id: 'cta', type: 'cta', x: (c) => (c.canvasWidth - 520) / 2, y: (c) => 880 + Math.min(c.qrSize, 480) + 40, width: 520, height: 100, align: 'center', fontSize: 30, fontFamily: 'Montserrat', lineHeight: 1.4 },
{ id: 'link', type: 'link', x: (c) => (c.canvasWidth - 600) / 2, y: (c) => 880 + Math.min(c.qrSize, 480) + 160, width: 600, height: 80, align: 'center', fontSize: 24, fontFamily: 'Montserrat' },
];
const gardenBrunchPreset: LayoutPreset = [
{ id: 'badge', type: 'badge', x: 180, y: 180, width: 500, height: 110, align: 'center', fontSize: 30 },
{ id: 'headline', type: 'headline', x: 180, y: 340, width: (context) => context.canvasWidth - 360, height: 260, fontSize: 86, align: 'left' },
{ id: 'description', type: 'description', x: 180, y: 630, width: (context) => context.canvasWidth - 360, height: 360, fontSize: 34, align: 'left' },
// Verspielt, asymmetrisch, aber ausbalanciert
{ id: 'badge', type: 'badge', x: 120, y: 120, width: 500, height: 90, align: 'left', fontSize: 28, fontFamily: 'Montserrat' },
{ id: 'headline', type: 'headline', x: 120, y: 240, width: 900, height: 200, fontSize: 90, align: 'left', fontFamily: 'Playfair Display', lineHeight: 1.3 },
{ id: 'subtitle', type: 'subtitle', x: 120, y: 450, width: 700, height: 120, fontSize: 40, align: 'left', fontFamily: 'Montserrat', lineHeight: 1.4 },
{
id: 'qr',
type: 'qr',
x: 180,
y: 1000,
width: (context) => Math.min(context.qrSize, 660),
height: (context) => Math.min(context.qrSize, 660),
x: 120,
y: 880,
width: (c) => Math.min(c.qrSize, 460),
height: (c) => Math.min(c.qrSize, 460),
},
{ id: 'cta', type: 'cta', x: 120, y: (c) => 880 + Math.min(c.qrSize, 460) + 40, width: 460, height: 100, align: 'center', fontSize: 30, fontFamily: 'Montserrat' },
{
id: 'link',
type: 'link',
x: 180,
y: (context) => 1060 + Math.min(context.qrSize, 660),
width: 520,
height: 140,
align: 'center',
id: 'description',
type: 'description',
x: (c) => c.canvasWidth - 600 - 120,
y: 620,
width: 600,
height: 400,
fontSize: 32,
align: 'left',
fontFamily: 'Lora',
lineHeight: 1.6,
},
{
id: 'cta',
type: 'cta',
x: 180,
y: (context) => 1100 + Math.min(context.qrSize, 660) + 190,
width: 520,
height: 140,
align: 'center',
},
{ id: 'subtitle', type: 'subtitle', x: (context) => context.canvasWidth - 460, y: 360, width: 420, height: 200, fontSize: 38, align: 'left' },
{ id: 'text-strip', type: 'text', x: (context) => context.canvasWidth - 460, y: 620, width: 420, height: 360, fontSize: 28, align: 'left' },
{ id: 'link', type: 'link', x: 120, y: (c) => 880 + Math.min(c.qrSize, 460) + 160, width: 460, height: 80, align: 'center', fontSize: 24 },
];
const sparklerSoireePreset: LayoutPreset = [
{ id: 'badge', type: 'badge', x: (context) => context.canvasWidth / 2 - 320, y: 200, width: 640, height: 120, align: 'center', fontSize: 32 },
// Festlich, zentriert, klar
{ id: 'badge', type: 'badge', x: (c) => (c.canvasWidth - 560) / 2, y: 120, width: 560, height: 90, align: 'center', fontSize: 28, fontFamily: 'Montserrat' },
{
id: 'headline',
type: 'headline',
x: (context) => context.canvasWidth / 2 - (context.canvasWidth - 220) / 2,
y: 360,
width: (context) => context.canvasWidth - 220,
height: 280,
fontSize: 94,
align: 'center',
},
{
id: 'subtitle',
type: 'subtitle',
x: (context) => context.canvasWidth / 2 - (context.canvasWidth - 320) / 2,
y: 660,
width: (context) => context.canvasWidth - 320,
height: 210,
fontSize: 46,
align: 'center',
},
{
id: 'description',
type: 'description',
x: (context) => context.canvasWidth / 2 - (context.canvasWidth - 320) / 2,
y: 920,
width: (context) => context.canvasWidth - 320,
height: 380,
fontSize: 34,
x: (c) => (c.canvasWidth - 1000) / 2,
y: 240,
width: 1000,
height: 220,
fontSize: 100,
align: 'center',
fontFamily: 'Playfair Display',
lineHeight: 1.3,
},
{ id: 'subtitle', type: 'subtitle', x: (c) => (c.canvasWidth - 800) / 2, y: 480, width: 800, height: 120, fontSize: 40, align: 'center', fontFamily: 'Montserrat' },
{ id: 'description', type: 'description', x: (c) => (c.canvasWidth - 900) / 2, y: 620, width: 900, height: 180, fontSize: 32, align: 'center', fontFamily: 'Lora', lineHeight: 1.5 },
{
id: 'qr',
type: 'qr',
x: (context) => (context.canvasWidth - Math.min(context.qrSize, 680)) / 2,
y: 1200,
width: (context) => Math.min(context.qrSize, 680),
height: (context) => Math.min(context.qrSize, 680),
},
{
id: 'link',
type: 'link',
x: (context) => (context.canvasWidth - 580) / 2,
y: (context) => 1260 + Math.min(context.qrSize, 680),
width: 580,
height: 150,
align: 'center',
},
{
id: 'cta',
type: 'cta',
x: (context) => (context.canvasWidth - 580) / 2,
y: (context) => 1300 + Math.min(context.qrSize, 680) + 200,
width: 580,
height: 150,
align: 'center',
x: (c) => (c.canvasWidth - 480) / 2,
y: 880,
width: (c) => Math.min(c.qrSize, 480),
height: (c) => Math.min(c.qrSize, 480),
},
{ id: 'cta', type: 'cta', x: (c) => (c.canvasWidth - 520) / 2, y: (c) => 880 + Math.min(c.qrSize, 480) + 40, width: 520, height: 100, align: 'center', fontSize: 30, fontFamily: 'Montserrat' },
{ id: 'link', type: 'link', x: (c) => (c.canvasWidth - 600) / 2, y: (c) => 880 + Math.min(c.qrSize, 480) + 160, width: 600, height: 80, align: 'center', fontSize: 24, fontFamily: 'Montserrat' },
];
const confettiBashPreset: LayoutPreset = [
{ id: 'badge', type: 'badge', x: 180, y: 220, width: 520, height: 120, align: 'center', fontSize: 32 },
// Zentriertes, luftiges Layout mit klarer Hierarchie.
{ id: 'logo', type: 'logo', x: (c) => (c.canvasWidth - 280) / 2, y: 80, width: 280, height: 140, align: 'center' },
{ id: 'badge', type: 'badge', x: (c) => (c.canvasWidth - 520) / 2, y: 240, width: 520, height: 90, align: 'center', fontSize: 28, lineHeight: 1.4, letterSpacing: 0.5, fontFamily: 'Montserrat' },
{
id: 'headline',
type: 'headline',
x: 180,
y: 380,
width: (context) => context.canvasWidth - 360,
height: 260,
fontSize: 90,
align: 'left',
x: (c) => (c.canvasWidth - 1000) / 2,
y: 350,
width: 1000,
height: 220,
fontSize: 110,
align: 'center',
fontFamily: 'Playfair Display',
lineHeight: 1.3,
},
{
id: 'subtitle',
type: 'subtitle',
x: 180,
y: 660,
width: (context) => context.canvasWidth - 360,
height: 200,
fontSize: 46,
align: 'left',
x: (c) => (c.canvasWidth - 800) / 2,
y: 580,
width: 800,
height: 120,
fontSize: 42,
align: 'center',
fontFamily: 'Montserrat',
lineHeight: 1.4,
},
{
id: 'description',
type: 'description',
x: 180,
y: 910,
width: (context) => context.canvasWidth - 360,
height: 360,
x: (c) => (c.canvasWidth - 900) / 2,
y: 720,
width: 900,
height: 180,
fontSize: 34,
align: 'left',
align: 'center',
fontFamily: 'Lora',
lineHeight: 1.5,
},
{
id: 'qr',
type: 'qr',
x: (context) => context.canvasWidth - Math.min(context.qrSize, 680) - 200,
y: 460,
width: (context) => Math.min(context.qrSize, 680),
height: (context) => Math.min(context.qrSize, 680),
},
{
id: 'link',
type: 'link',
x: (context) => context.canvasWidth - 560,
y: (context) => 520 + Math.min(context.qrSize, 680),
width: 520,
height: 140,
align: 'center',
x: (c) => (c.canvasWidth - 500) / 2,
y: 940,
width: (c) => Math.min(c.qrSize, 500),
height: (c) => Math.min(c.qrSize, 500),
},
{
id: 'cta',
type: 'cta',
x: (context) => context.canvasWidth - 560,
y: (context) => 560 + Math.min(context.qrSize, 680) + 200,
width: 520,
height: 140,
x: (c) => (c.canvasWidth - 600) / 2,
y: (c) => 940 + Math.min(c.qrSize, 500) + 40,
width: 600,
height: 100,
align: 'center',
fontSize: 32,
fontFamily: 'Montserrat',
lineHeight: 1.4,
},
{
id: 'text-strip',
type: 'text',
x: 180,
y: 1220,
width: (context) => context.canvasWidth - 360,
height: 360,
fontSize: 30,
align: 'left',
id: 'link',
type: 'link',
x: (c) => (c.canvasWidth - 700) / 2,
y: (c) => 940 + Math.min(c.qrSize, 500) + 160,
width: 700,
height: 80,
align: 'center',
fontSize: 26,
fontFamily: 'Montserrat',
lineHeight: 1.5,
},
];
const balancedModernPreset: LayoutPreset = [
// Wahrhaftig balanciert: Text links, QR rechts
{ id: 'logo', type: 'logo', x: 120, y: 100, width: 300, height: 150, align: 'left' },
{ id: 'badge', type: 'badge', x: 120, y: 270, width: 500, height: 90, align: 'left', fontSize: 28, fontFamily: 'Montserrat' },
{
id: 'headline',
type: 'headline',
x: 120,
y: 380,
width: 620,
height: 380,
fontSize: 100,
align: 'left',
fontFamily: 'Playfair Display',
lineHeight: 1.3,
},
{
id: 'subtitle',
type: 'subtitle',
x: 120,
y: 770,
width: 620,
height: 140,
fontSize: 42,
align: 'left',
fontFamily: 'Montserrat',
lineHeight: 1.4,
},
{
id: 'description',
type: 'description',
x: 120,
y: 920,
width: 620,
height: 300,
fontSize: 34,
align: 'left',
fontFamily: 'Lora',
lineHeight: 1.5,
},
{
id: 'qr',
type: 'qr',
x: (c) => c.canvasWidth - 480 - 120,
y: 380,
width: 480,
height: 480,
},
{ id: 'cta', type: 'cta', x: (c) => c.canvasWidth - 480 - 120, y: 880, width: 480, height: 100, align: 'center', fontSize: 30, fontFamily: 'Montserrat' },
{ id: 'link', type: 'link', x: (c) => c.canvasWidth - 480 - 120, y: 1000, width: 480, height: 80, align: 'center', fontSize: 24, fontFamily: 'Montserrat' },
];
const LAYOUT_PRESETS: Record<string, LayoutPreset> = {
'default': DEFAULT_PRESET,
'evergreen-vows': evergreenVowsPreset,
'midnight-gala': midnightGalaPreset,
'garden-brunch': gardenBrunchPreset,
'sparkler-soiree': sparklerSoireePreset,
'confetti-bash': confettiBashPreset,
'default': DEFAULT_PRESET,
'evergreen-vows': evergreenVowsPreset,
'midnight-gala': midnightGalaPreset,
'garden-brunch': gardenBrunchPreset,
'sparkler-soiree': sparklerSoireePreset,
'confetti-bash': confettiBashPreset,
'balanced-modern': balancedModernPreset, // New preset: QR right, text left, logo top
};
function resolvePresetValue(value: PresetValue | undefined, context: LayoutPresetContext, fallback: number): number {
@@ -554,13 +507,14 @@ export function buildDefaultElements(
height: resolvePresetValue(config.height, context, heightFallback),
fontSize: config.fontSize ?? typeStyle.fontSize,
align: config.align ?? typeStyle.align ?? 'left',
fontFamily: config.fontFamily ?? 'Lora',
content: null,
locked: config.locked ?? typeStyle.locked ?? false,
initial: config.initial ?? true,
};
if (config.type === 'description') {
element.lineHeight = 1.4;
element.lineHeight = 1.5;
}
switch (config.id) {
@@ -622,6 +576,8 @@ export function payloadToElements(payload?: LayoutElementPayload[] | null): Layo
y: Number(entry.y ?? 0),
width: Number(entry.width ?? 100),
height: Number(entry.height ?? 100),
scaleX: Number(entry.scale_x ?? 1),
scaleY: Number(entry.scale_y ?? 1),
rotation: typeof entry.rotation === 'number' ? entry.rotation : 0,
fontSize: typeof entry.font_size === 'number' ? entry.font_size : undefined,
align: entry.align ?? 'left',
@@ -644,6 +600,8 @@ export function elementsToPayload(elements: LayoutElement[]): LayoutElementPaylo
y: element.y,
width: element.width,
height: element.height,
scale_x: element.scaleX ?? 1,
scale_y: element.scaleY ?? 1,
rotation: element.rotation ?? 0,
font_size: element.fontSize,
align: element.align,