x
This commit is contained in:
1 parent
dba82b26a8
commit
943fd8f1a3
16 files changed
+257
-20
No files matched your search
@@ -110,6 +110,8 @@ export default function BannerForm({
|
|||||||
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
||||||
textColorScheme={editingSection.payload?.textColorScheme}
|
textColorScheme={editingSection.payload?.textColorScheme}
|
||||||
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
||||||
|
titleSize={editingSection.payload?.titleSize}
|
||||||
|
onChangeTitleSize={(size) => updatePayloadValue('titleSize', size)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Monitor, Smartphone, RotateCcw, Maximize2, Sun, Moon, Palette } from 'lucide-react';
|
import { Monitor, Smartphone, RotateCcw, Maximize2, Sun, Moon, Palette, Type } from 'lucide-react';
|
||||||
|
|
||||||
export const GRID_POSITIONS = [
|
export const GRID_POSITIONS = [
|
||||||
{ id: 'top-left', label: 'Top Left (บนซ้าย)', short: 'TL', icon: '↖' },
|
{ id: 'top-left', label: 'Top Left (บนซ้าย)', short: 'TL', icon: '↖' },
|
||||||
@@ -18,6 +18,13 @@ export const WIDTH_OPTIONS = [
|
|||||||
{ id: 'compact', label: 'กรอบกระชับ (768px)', desc: 'กล่องกะทัดรัด max-w-3xl' },
|
{ id: 'compact', label: 'กรอบกระชับ (768px)', desc: 'กล่องกะทัดรัด max-w-3xl' },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
export const TITLE_SIZE_OPTIONS = [
|
||||||
|
{ id: 'sm', label: 'กะทัดรัด (Small / 44px)', desc: 'เหมาะกับข้อความยาว หรือภาพที่มีสินค้าเด่นด้านข้าง ไม่ชนสินค้า' },
|
||||||
|
{ id: 'md', label: 'ปานกลาง (Medium / 60px)', desc: 'ขนาดมาตรฐานบทความ / Heading ชัดเจน ไม่ล้นจอ' },
|
||||||
|
{ id: 'lg', label: 'ใหญ่ (Large / 76px)', desc: 'ขนาดโปรโมชัน เน้นตัวอักษรเด่นและสะดุดตา' },
|
||||||
|
{ id: 'xl', label: 'ยักษ์ (Display / 96px)', desc: 'ขนาดดั้งเดิม (Display Huge) เหมาะกับคำสั้น 2-3 คำ' },
|
||||||
|
] as const;
|
||||||
|
|
||||||
export const COLOR_SCHEME_OPTIONS = [
|
export const COLOR_SCHEME_OPTIONS = [
|
||||||
{
|
{
|
||||||
id: 'light',
|
id: 'light',
|
||||||
@@ -45,6 +52,8 @@ export interface ContentPositionPickerProps {
|
|||||||
onChangeContentWidth?: (width: string) => void;
|
onChangeContentWidth?: (width: string) => void;
|
||||||
textColorScheme?: 'light' | 'dark' | string;
|
textColorScheme?: 'light' | 'dark' | string;
|
||||||
onChangeTextColorScheme?: (scheme: 'light' | 'dark') => void;
|
onChangeTextColorScheme?: (scheme: 'light' | 'dark') => void;
|
||||||
|
titleSize?: 'sm' | 'md' | 'lg' | 'xl' | string;
|
||||||
|
onChangeTitleSize?: (size: string) => void;
|
||||||
title?: string;
|
title?: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
@@ -60,6 +69,8 @@ export default function ContentPositionPicker({
|
|||||||
onChangeContentWidth,
|
onChangeContentWidth,
|
||||||
textColorScheme,
|
textColorScheme,
|
||||||
onChangeTextColorScheme,
|
onChangeTextColorScheme,
|
||||||
|
titleSize,
|
||||||
|
onChangeTitleSize,
|
||||||
title = 'ตำแหน่งปุ่ม & เนื้อหา (Button & Content Position)',
|
title = 'ตำแหน่งปุ่ม & เนื้อหา (Button & Content Position)',
|
||||||
subtitle = 'สามารถแยกตำแหน่งระหว่าง Desktop (PC) และ Mobile (มือถือ) ได้อิสระ',
|
subtitle = 'สามารถแยกตำแหน่งระหว่าง Desktop (PC) และ Mobile (มือถือ) ได้อิสระ',
|
||||||
compact = false,
|
compact = false,
|
||||||
@@ -255,6 +266,43 @@ export default function ContentPositionPicker({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Title Size / Heading Scale Preset Selection */}
|
||||||
|
{onChangeTitleSize && (
|
||||||
|
<div className="bg-night-950/40 border border-white/5 p-3 rounded-2xl space-y-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-[11px] font-bold uppercase tracking-wider text-slate-300 flex items-center gap-1.5">
|
||||||
|
<Type className="w-3.5 h-3.5 text-cyan-glow" />
|
||||||
|
ขนาดตัวอักษรหัวข้อ (Title Font Size Preset)
|
||||||
|
</span>
|
||||||
|
<span className="px-2 py-0.5 rounded-md bg-cyan-glow/10 text-cyan-glow font-mono font-bold text-[10px] border border-cyan-glow/20">
|
||||||
|
{(titleSize || 'xl').toUpperCase()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-2">
|
||||||
|
{TITLE_SIZE_OPTIONS.map((opt) => {
|
||||||
|
const isSelected = (titleSize || 'xl') === opt.id;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={opt.id}
|
||||||
|
type="button"
|
||||||
|
onClick={() => onChangeTitleSize(opt.id)}
|
||||||
|
className={`px-3 py-2.5 rounded-xl text-left transition-all border cursor-pointer ${
|
||||||
|
isSelected
|
||||||
|
? 'bg-cyan-glow/15 border-cyan-glow/50 text-white shadow-sm ring-1 ring-cyan-glow/30'
|
||||||
|
: 'bg-night-900 border-white/5 text-slate-400 hover:text-white hover:border-white/10'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-xs font-bold leading-tight">{opt.label}</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-[9px] text-slate-500 mt-1 leading-tight">{opt.desc}</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -72,6 +72,20 @@ export default function HeroArticleForm({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">Title Font Size</label>
|
||||||
|
<select
|
||||||
|
value={editingSection.payload?.titleSize || 'xl'}
|
||||||
|
onChange={(e) => updatePayloadValue('titleSize', e.target.value)}
|
||||||
|
className="admin-input w-full bg-slate-900 border-white/10"
|
||||||
|
>
|
||||||
|
<option value="sm">Small (กะทัดรัด / 44px)</option>
|
||||||
|
<option value="md">Medium (ปานกลาง / 60px)</option>
|
||||||
|
<option value="lg">Large (ใหญ่ / 76px)</option>
|
||||||
|
<option value="xl">Display (ยักษ์ / 96px)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">Author</label>
|
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">Author</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -236,6 +236,8 @@ export default function HeroForm({
|
|||||||
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
||||||
textColorScheme={editingSection.payload?.textColorScheme}
|
textColorScheme={editingSection.payload?.textColorScheme}
|
||||||
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
||||||
|
titleSize={editingSection.payload?.titleSize}
|
||||||
|
onChangeTitleSize={(size) => updatePayloadValue('titleSize', size)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -71,6 +71,20 @@ export default function HeroV2Form({
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">Title Font Size</label>
|
||||||
|
<select
|
||||||
|
value={editingSection.payload?.titleSize || 'lg'}
|
||||||
|
onChange={(e) => updatePayloadValue('titleSize', e.target.value)}
|
||||||
|
className="admin-input w-full bg-slate-900 border-white/10"
|
||||||
|
>
|
||||||
|
<option value="sm">Small (กะทัดรัด / 44px)</option>
|
||||||
|
<option value="md">Medium (ปานกลาง / 60px)</option>
|
||||||
|
<option value="lg">Large (ใหญ่ / 76px)</option>
|
||||||
|
<option value="xl">Display (ยักษ์ / 96px)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2 flex items-center gap-2 pt-6">
|
<div className="space-y-2 flex items-center gap-2 pt-6">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
|||||||
@@ -303,6 +303,8 @@ export default function HeroVideoForm({
|
|||||||
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
||||||
textColorScheme={payload.textColorScheme}
|
textColorScheme={payload.textColorScheme}
|
||||||
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
||||||
|
titleSize={payload.titleSize}
|
||||||
|
onChangeTitleSize={(size) => updatePayloadValue('titleSize', size)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ const validHeroCarouselPayload = {
|
|||||||
subtitle: { th: "ข้อความรอง", en: "Supporting copy" },
|
subtitle: { th: "ข้อความรอง", en: "Supporting copy" },
|
||||||
buttonText: { th: "ดูสินค้า", en: "View product" },
|
buttonText: { th: "ดูสินค้า", en: "View product" },
|
||||||
focalPoint: { x: "50%", y: "45%" },
|
focalPoint: { x: "50%", y: "45%" },
|
||||||
|
buttonPosition: "bottom-left",
|
||||||
|
contentWidth: "standard",
|
||||||
|
textColorScheme: "light",
|
||||||
|
titleSize: "xl",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Elysia, t } from "elysia";
|
import { Elysia, t } from "elysia";
|
||||||
import prisma from "../lib/prisma";
|
import prisma from "../lib/prisma";
|
||||||
// Trigger reload: support containerWidth, cardSize, and layout for PRODUCT_CAROUSEL and PRODUCTS
|
// Trigger reload: support titleSize in HERO and HERO_VIDEO payloads
|
||||||
import {
|
import {
|
||||||
LocalizedStringSchema,
|
LocalizedStringSchema,
|
||||||
HeroSectionPayloadSchema,
|
HeroSectionPayloadSchema,
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ const PAGE_BLOCK_METADATA: Record<string, BlockMetadata> = {
|
|||||||
HERO: {
|
HERO: {
|
||||||
type: "HERO",
|
type: "HERO",
|
||||||
requiredFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink"],
|
requiredFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink"],
|
||||||
optionalFields: ["focalPoint"],
|
optionalFields: ["focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize"],
|
||||||
renderedFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink", "focalPoint"],
|
renderedFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink", "focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize"],
|
||||||
storedOnlyFields: [],
|
storedOnlyFields: [],
|
||||||
discoveryToolsNeeded: [],
|
discoveryToolsNeeded: [],
|
||||||
warnings: ["Use an image URL from a host allowed by apps/website next.config.ts."],
|
warnings: ["Use an image URL from a host allowed by apps/website next.config.ts."],
|
||||||
@@ -669,8 +669,8 @@ const PAGE_BLOCK_METADATA: Record<string, BlockMetadata> = {
|
|||||||
HERO_V2: {
|
HERO_V2: {
|
||||||
type: "HERO_V2",
|
type: "HERO_V2",
|
||||||
requiredFields: ["title", "imageUrl"],
|
requiredFields: ["title", "imageUrl"],
|
||||||
optionalFields: ["tagline", "description", "contentAlignment", "showOrnament", "primaryButtonText", "primaryButtonLink", "secondaryButtonText", "secondaryButtonLink", "focalPoint"],
|
optionalFields: ["tagline", "description", "contentAlignment", "showOrnament", "primaryButtonText", "primaryButtonLink", "secondaryButtonText", "secondaryButtonLink", "focalPoint", "titleSize"],
|
||||||
renderedFields: ["tagline", "title", "description", "imageUrl", "contentAlignment", "showOrnament", "primaryButtonText", "primaryButtonLink", "secondaryButtonText", "secondaryButtonLink", "focalPoint"],
|
renderedFields: ["tagline", "title", "description", "imageUrl", "contentAlignment", "showOrnament", "primaryButtonText", "primaryButtonLink", "secondaryButtonText", "secondaryButtonLink", "focalPoint", "titleSize"],
|
||||||
storedOnlyFields: [],
|
storedOnlyFields: [],
|
||||||
discoveryToolsNeeded: [],
|
discoveryToolsNeeded: [],
|
||||||
warnings: ["contentAlignment must be left, center, or right. Use an image URL allowed by apps/website."],
|
warnings: ["contentAlignment must be left, center, or right. Use an image URL allowed by apps/website."],
|
||||||
|
|||||||
@@ -151,6 +151,20 @@ export function getHeroContainerWidthClasses(contentWidth?: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getHeroTitleSizeClass(titleSize?: string): string {
|
||||||
|
switch (titleSize) {
|
||||||
|
case 'sm':
|
||||||
|
return 'ui-hero-title-sm';
|
||||||
|
case 'md':
|
||||||
|
return 'ui-hero-title-md';
|
||||||
|
case 'lg':
|
||||||
|
return 'ui-hero-title-lg';
|
||||||
|
case 'xl':
|
||||||
|
default:
|
||||||
|
return 'ui-hero-title-xl';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function DynamicHero({ payload }: DynamicHeroProps) {
|
export default function DynamicHero({ payload }: DynamicHeroProps) {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const lang = i18n.language;
|
const lang = i18n.language;
|
||||||
@@ -240,6 +254,9 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const containerClasses = getHeroContainerWidthClasses(contentWidth);
|
const containerClasses = getHeroContainerWidthClasses(contentWidth);
|
||||||
|
const titleSize = (payload as any).titleSize || 'xl';
|
||||||
|
const titleSizeClass = getHeroTitleSizeClass(titleSize);
|
||||||
|
const textWrapperWidthClass = titleSize === 'sm' || contentWidth === 'compact' ? 'max-w-xl' : titleSize === 'md' ? 'max-w-2xl' : 'max-w-3xl';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`relative w-full min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9] flex overflow-hidden ${isDarkText ? 'bg-surface-page' : 'bg-night-950'}`}>
|
<section className={`relative w-full min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9] flex overflow-hidden ${isDarkText ? 'bg-surface-page' : 'bg-night-950'}`}>
|
||||||
@@ -258,14 +275,14 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={`relative z-10 min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${containerClasses} ${wrapperClasses} animate-fade-in`}>
|
<div className={`relative z-10 min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${containerClasses} ${wrapperClasses} animate-fade-in`}>
|
||||||
<div className={`w-full max-w-3xl flex flex-col space-y-5 ${contentClasses}`}>
|
<div className={`w-full ${textWrapperWidthClass} flex flex-col space-y-5 ${contentClasses}`}>
|
||||||
{tagline && (
|
{tagline && (
|
||||||
<p className={`${isDarkText ? 'text-pop-pink' : 'text-pop-yellow'} font-semibold tracking-[0.3em] text-xs md:text-sm uppercase drop-shadow-md`}>
|
<p className={`${isDarkText ? 'text-pop-pink' : 'text-pop-yellow'} font-semibold tracking-[0.3em] text-xs md:text-sm uppercase drop-shadow-md`}>
|
||||||
{tagline}
|
{tagline}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{title && (
|
{title && (
|
||||||
<h1 className={`ui-hero-title ${isDarkText ? '!text-pop-black' : '!text-white'} drop-shadow-lg`}>
|
<h1 className={`ui-hero-title ${titleSizeClass} ${isDarkText ? '!text-pop-black' : '!text-white'} drop-shadow-lg`}>
|
||||||
{renderTitle(title)}
|
{renderTitle(title)}
|
||||||
</h1>
|
</h1>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { getLocalizedField } from '../utils/localization';
|
import { getLocalizedField } from '../utils/localization';
|
||||||
import { Sparkles, ChevronRight } from 'lucide-react';
|
import { Sparkles, ChevronRight } from 'lucide-react';
|
||||||
|
import { getHeroTitleSizeClass } from './DynamicHero';
|
||||||
|
|
||||||
interface DynamicHeroV2Props {
|
interface DynamicHeroV2Props {
|
||||||
payload: Record<string, any>;
|
payload: Record<string, any>;
|
||||||
@@ -68,7 +69,7 @@ export default function DynamicHeroV2({ payload }: DynamicHeroV2Props) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-serif text-pop-black leading-tight">
|
<h1 className={`font-serif ui-hero-title ${getHeroTitleSizeClass((payload as any).titleSize)} text-pop-black leading-tight`}>
|
||||||
{renderTitle(title || '')}
|
{renderTitle(title || '')}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import type { HeroVideoSectionPayload } from '@homaroma/types';
|
import type { HeroVideoSectionPayload } from '@homaroma/types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { getLocalizedField } from '../utils/localization';
|
import { getLocalizedField } from '../utils/localization';
|
||||||
import { getHeroPositionClasses, getHeroContainerWidthClasses } from './DynamicHero';
|
import { getHeroPositionClasses, getHeroContainerWidthClasses, getHeroTitleSizeClass } from './DynamicHero';
|
||||||
|
|
||||||
interface DynamicHeroVideoProps {
|
interface DynamicHeroVideoProps {
|
||||||
payload: HeroVideoSectionPayload;
|
payload: HeroVideoSectionPayload;
|
||||||
@@ -98,6 +98,9 @@ export default function DynamicHeroVideo({ payload }: DynamicHeroVideoProps) {
|
|||||||
const desktopPosition = (payload as any).buttonPosition || 'center';
|
const desktopPosition = (payload as any).buttonPosition || 'center';
|
||||||
const mobilePosition = (payload as any).mobileButtonPosition || desktopPosition;
|
const mobilePosition = (payload as any).mobileButtonPosition || desktopPosition;
|
||||||
const contentWidth = (payload as any).contentWidth || 'standard';
|
const contentWidth = (payload as any).contentWidth || 'standard';
|
||||||
|
const titleSize = (payload as any).titleSize || 'xl';
|
||||||
|
const titleSizeClass = getHeroTitleSizeClass(titleSize);
|
||||||
|
const textWrapperWidthClass = titleSize === 'sm' || contentWidth === 'compact' ? 'max-w-xl' : titleSize === 'md' ? 'max-w-2xl' : 'max-w-3xl';
|
||||||
const { wrapperClasses, contentClasses, actionsClasses } = getHeroPositionClasses(mobilePosition, desktopPosition);
|
const { wrapperClasses, contentClasses, actionsClasses } = getHeroPositionClasses(mobilePosition, desktopPosition);
|
||||||
const containerClasses = getHeroContainerWidthClasses(contentWidth);
|
const containerClasses = getHeroContainerWidthClasses(contentWidth);
|
||||||
|
|
||||||
@@ -109,14 +112,14 @@ export default function DynamicHeroVideo({ payload }: DynamicHeroVideoProps) {
|
|||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div className={`relative z-20 py-16 h-full flex flex-col animate-fade-in ${containerClasses} ${wrapperClasses}`}>
|
<div className={`relative z-20 py-16 h-full flex flex-col animate-fade-in ${containerClasses} ${wrapperClasses}`}>
|
||||||
<div className={`flex flex-col space-y-6 max-w-3xl ${contentClasses}`}>
|
<div className={`flex flex-col space-y-6 ${textWrapperWidthClass} ${contentClasses}`}>
|
||||||
{tagline && (
|
{tagline && (
|
||||||
<p className="text-xs md:text-sm font-semibold uppercase tracking-[0.35em] text-pop-pink drop-shadow-md">
|
<p className="text-xs md:text-sm font-semibold uppercase tracking-[0.35em] text-pop-pink drop-shadow-md">
|
||||||
{tagline}
|
{tagline}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<h1 className={`font-serif text-4xl md:text-6xl lg:text-7xl font-light leading-tight tracking-wide drop-shadow-lg ${isDarkText ? 'text-pop-black' : 'text-white'}`}>
|
<h1 className={`font-serif ui-hero-title ${titleSizeClass} font-light leading-tight tracking-wide drop-shadow-lg ${isDarkText ? '!text-pop-black' : '!text-white'}`}>
|
||||||
{renderTitle(title) || renderTitle(t('hero.defaultTitle'))}
|
{renderTitle(title) || renderTitle(t('hero.defaultTitle'))}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,22 @@
|
|||||||
color: var(--color-pop-black);
|
color: var(--color-pop-black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-sm {
|
||||||
|
@apply !text-2xl sm:!text-3xl md:!text-4xl lg:!text-5xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-md {
|
||||||
|
@apply !text-3xl sm:!text-4xl md:!text-5xl lg:!text-6xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-lg {
|
||||||
|
@apply !text-4xl sm:!text-5xl md:!text-6xl lg:!text-7xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-xl {
|
||||||
|
@apply !text-5xl md:!text-7xl lg:!text-8xl;
|
||||||
|
}
|
||||||
|
|
||||||
.ui-hero-copy {
|
.ui-hero-copy {
|
||||||
@apply mx-auto max-w-2xl pb-8 pt-4 text-lg font-light drop-shadow-md md:text-xl;
|
@apply mx-auto max-w-2xl pb-8 pt-4 text-lg font-light drop-shadow-md md:text-xl;
|
||||||
color: var(--color-pop-black);
|
color: var(--color-pop-black);
|
||||||
|
|||||||
@@ -451,6 +451,26 @@
|
|||||||
filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));
|
filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-sm {
|
||||||
|
font-size: 1.75rem !important;
|
||||||
|
line-height: 1.2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-md {
|
||||||
|
font-size: 2.25rem !important;
|
||||||
|
line-height: 1.2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-lg {
|
||||||
|
font-size: 2.75rem !important;
|
||||||
|
line-height: 1.15 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-xl {
|
||||||
|
font-size: 3rem !important;
|
||||||
|
line-height: 1.25 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ui-hero-copy {
|
.ui-hero-copy {
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
max-width: 42rem;
|
max-width: 42rem;
|
||||||
@@ -568,6 +588,26 @@
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-sm {
|
||||||
|
font-size: 2.25rem !important;
|
||||||
|
line-height: 1.15 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-md {
|
||||||
|
font-size: 3rem !important;
|
||||||
|
line-height: 1.15 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-lg {
|
||||||
|
font-size: 3.75rem !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-xl {
|
||||||
|
font-size: 4.5rem !important;
|
||||||
|
line-height: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ui-hero-copy {
|
.ui-hero-copy {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
line-height: 1.75rem;
|
line-height: 1.75rem;
|
||||||
@@ -588,6 +628,26 @@
|
|||||||
font-size: 6rem;
|
font-size: 6rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-sm {
|
||||||
|
font-size: 2.75rem !important;
|
||||||
|
line-height: 1.1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-md {
|
||||||
|
font-size: 3.75rem !important;
|
||||||
|
line-height: 1.05 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-lg {
|
||||||
|
font-size: 4.75rem !important;
|
||||||
|
line-height: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-hero-title-xl {
|
||||||
|
font-size: 6rem !important;
|
||||||
|
line-height: 1 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-panel {
|
.ui-panel {
|
||||||
|
|||||||
@@ -273,6 +273,35 @@ function getHeroContainerWidthClasses(contentWidth?: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getHeroTitleSizeClass(titleSize?: unknown): string {
|
||||||
|
switch (titleSize) {
|
||||||
|
case 'sm':
|
||||||
|
return 'ui-hero-title-sm'
|
||||||
|
case 'md':
|
||||||
|
return 'ui-hero-title-md'
|
||||||
|
case 'lg':
|
||||||
|
return 'ui-hero-title-lg'
|
||||||
|
case 'xl':
|
||||||
|
default:
|
||||||
|
return 'ui-hero-title-xl'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTailwindHeroTitleClass(titleSize?: unknown, defaultSize = 'xl'): string {
|
||||||
|
const size = (titleSize || defaultSize) as string
|
||||||
|
switch (size) {
|
||||||
|
case 'sm':
|
||||||
|
return 'text-2xl sm:text-3xl md:text-4xl'
|
||||||
|
case 'md':
|
||||||
|
return 'text-3xl sm:text-4xl md:text-5xl'
|
||||||
|
case 'lg':
|
||||||
|
return 'text-4xl sm:text-5xl md:text-6xl'
|
||||||
|
case 'xl':
|
||||||
|
default:
|
||||||
|
return 'text-4xl sm:text-5xl md:text-6xl lg:text-7xl'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang: string }) {
|
function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang: string }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const i18nLang = useLang()
|
const i18nLang = useLang()
|
||||||
@@ -288,6 +317,9 @@ function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang
|
|||||||
const contentWidth = typeof payload.contentWidth === 'string' ? payload.contentWidth : 'standard'
|
const contentWidth = typeof payload.contentWidth === 'string' ? payload.contentWidth : 'standard'
|
||||||
const textColorScheme = typeof payload.textColorScheme === 'string' ? payload.textColorScheme : 'light'
|
const textColorScheme = typeof payload.textColorScheme === 'string' ? payload.textColorScheme : 'light'
|
||||||
const isDarkText = textColorScheme === 'dark'
|
const isDarkText = textColorScheme === 'dark'
|
||||||
|
const titleSize = typeof payload.titleSize === 'string' ? payload.titleSize : 'xl'
|
||||||
|
const titleSizeClass = getHeroTitleSizeClass(titleSize)
|
||||||
|
const textWrapperWidthClass = titleSize === 'sm' || contentWidth === 'compact' ? 'max-w-xl' : titleSize === 'md' ? 'max-w-2xl' : 'max-w-3xl'
|
||||||
const focalPoint = typeof payload.focalPoint === 'object' && payload.focalPoint ? (payload.focalPoint as { x: string, y: string }) : undefined
|
const focalPoint = typeof payload.focalPoint === 'object' && payload.focalPoint ? (payload.focalPoint as { x: string, y: string }) : undefined
|
||||||
|
|
||||||
// If fields are explicitly defined as empty strings, respect them as empty
|
// If fields are explicitly defined as empty strings, respect them as empty
|
||||||
@@ -357,14 +389,14 @@ function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang
|
|||||||
{renderOverlay()}
|
{renderOverlay()}
|
||||||
</div>
|
</div>
|
||||||
<div className={`relative z-10 min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${containerClasses} ${wrapperClasses}`}>
|
<div className={`relative z-10 min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${containerClasses} ${wrapperClasses}`}>
|
||||||
<div className={`w-full max-w-3xl flex flex-col space-y-5 ${contentClasses}`}>
|
<div className={`w-full ${textWrapperWidthClass} flex flex-col space-y-5 ${contentClasses}`}>
|
||||||
{tagline && (
|
{tagline && (
|
||||||
<p className={`text-xs font-semibold uppercase tracking-[0.3em] drop-shadow-md md:text-sm ${isDarkText ? 'text-brand-primary' : 'text-brand-accent'}`}>
|
<p className={`text-xs font-semibold uppercase tracking-[0.3em] drop-shadow-md md:text-sm ${isDarkText ? 'text-brand-primary' : 'text-brand-accent'}`}>
|
||||||
{tagline}
|
{tagline}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{title && (
|
{title && (
|
||||||
<h1 className={`ui-hero-title ${isDarkText ? '!text-text-main' : '!text-white'} drop-shadow-lg`}>
|
<h1 className={`ui-hero-title ${titleSizeClass} ${isDarkText ? '!text-text-main' : '!text-white'} drop-shadow-lg`}>
|
||||||
{renderAccentTitle(title, isDarkText ? 'text-brand-primary font-medium' : 'ui-accent-text font-medium')}
|
{renderAccentTitle(title, isDarkText ? 'text-brand-primary font-medium' : 'ui-accent-text font-medium')}
|
||||||
</h1>
|
</h1>
|
||||||
)}
|
)}
|
||||||
@@ -607,14 +639,14 @@ function HeroVideoSection({ payload, lang }: { payload: Record<string, unknown>,
|
|||||||
<div className={`absolute inset-0 z-10 transition-opacity ${isDarkText ? 'bg-white' : 'bg-black'}`} style={{ opacity: overlayOpacity / 100 }}></div>
|
<div className={`absolute inset-0 z-10 transition-opacity ${isDarkText ? 'bg-white' : 'bg-black'}`} style={{ opacity: overlayOpacity / 100 }}></div>
|
||||||
|
|
||||||
<div className={`relative z-20 py-16 h-full flex flex-col ${containerClasses} ${wrapperClasses}`}>
|
<div className={`relative z-20 py-16 h-full flex flex-col ${containerClasses} ${wrapperClasses}`}>
|
||||||
<div className={`flex flex-col space-y-6 max-w-3xl ${contentClasses}`}>
|
<div className={`flex flex-col space-y-6 ${payload.titleSize === 'sm' || contentWidth === 'compact' ? 'max-w-xl' : payload.titleSize === 'md' ? 'max-w-2xl' : 'max-w-3xl'} ${contentClasses}`}>
|
||||||
{tagline && (
|
{tagline && (
|
||||||
<p className={`text-xs md:text-sm font-semibold uppercase tracking-[0.35em] drop-shadow-md ${isDarkText ? 'text-brand-primary' : 'text-brand-accent'}`}>
|
<p className={`text-xs md:text-sm font-semibold uppercase tracking-[0.35em] drop-shadow-md ${isDarkText ? 'text-brand-primary' : 'text-brand-accent'}`}>
|
||||||
{tagline}
|
{tagline}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{title && (
|
{title && (
|
||||||
<h1 className={`font-serif text-4xl md:text-6xl lg:text-7xl font-light leading-tight tracking-wide drop-shadow-lg ${isDarkText ? 'text-text-main' : 'text-white'}`}>
|
<h1 className={`font-serif ${getTailwindHeroTitleClass(payload.titleSize, 'xl')} font-light leading-tight tracking-wide drop-shadow-lg ${isDarkText ? 'text-text-main' : 'text-white'}`}>
|
||||||
{renderAccentTitle(title, isDarkText ? 'text-brand-primary font-medium' : undefined)}
|
{renderAccentTitle(title, isDarkText ? 'text-brand-primary font-medium' : undefined)}
|
||||||
</h1>
|
</h1>
|
||||||
)}
|
)}
|
||||||
@@ -1012,7 +1044,7 @@ function HeroV2Section({ payload, lang }: { payload: Record<string, unknown>, la
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-serif text-text-main leading-tight">
|
<h1 className={`${getTailwindHeroTitleClass(payload.titleSize, 'lg')} font-serif text-text-main leading-tight`}>
|
||||||
{renderAccentTitle(title || '', 'text-brand-primary')}
|
{renderAccentTitle(title || '', 'text-brand-primary')}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -1271,8 +1303,12 @@ function BannerSection({ payload, lang }: { payload: Record<string, unknown>, la
|
|||||||
style={{ objectPosition: focalPoint ? `${focalPoint.x} ${focalPoint.y}` : undefined }}
|
style={{ objectPosition: focalPoint ? `${focalPoint.x} ${focalPoint.y}` : undefined }}
|
||||||
/>
|
/>
|
||||||
<div className={isDarkText ? "absolute inset-0 bg-white/40 backdrop-blur-[1px]" : "ui-banner-overlay"} />
|
<div className={isDarkText ? "absolute inset-0 bg-white/40 backdrop-blur-[1px]" : "ui-banner-overlay"} />
|
||||||
<div className={`ui-banner-content flex flex-col space-y-4 max-w-2xl ${bContent}`}>
|
<div className={`ui-banner-content flex flex-col space-y-4 ${payload.titleSize === 'sm' || contentWidth === 'compact' ? 'max-w-xl' : 'max-w-2xl'} ${bContent}`}>
|
||||||
{title && <h2 className={`text-3xl font-semibold drop-shadow-md md:text-5xl ${isDarkText ? '!text-text-main' : 'text-brand-primary'}`}>{title}</h2>}
|
{title && (
|
||||||
|
<h2 className={`${payload.titleSize === 'sm' ? 'text-2xl md:text-3xl' : payload.titleSize === 'md' ? 'text-2xl md:text-4xl' : payload.titleSize === 'lg' ? 'text-3xl md:text-5xl' : 'text-3xl md:text-5xl font-semibold'} drop-shadow-md ${isDarkText ? '!text-text-main' : 'text-brand-primary'}`}>
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
)}
|
||||||
{description && <p className={`drop-shadow-sm ${isDarkText ? '!text-text-main/80' : 'text-surface-page/90'}`}>{description}</p>}
|
{description && <p className={`drop-shadow-sm ${isDarkText ? '!text-text-main/80' : 'text-surface-page/90'}`}>{description}</p>}
|
||||||
{buttonText && (
|
{buttonText && (
|
||||||
<div className={`flex ${bActions}`}>
|
<div className={`flex ${bActions}`}>
|
||||||
@@ -2180,7 +2216,7 @@ function HeroArticleSection({ payload, lang }: { payload: Record<string, unknown
|
|||||||
)}
|
)}
|
||||||
<div className="relative z-10 mx-auto max-w-4xl space-y-6">
|
<div className="relative z-10 mx-auto max-w-4xl space-y-6">
|
||||||
{category && <p className="text-xs font-bold uppercase tracking-[0.28em] text-brand-accent">{category}</p>}
|
{category && <p className="text-xs font-bold uppercase tracking-[0.28em] text-brand-accent">{category}</p>}
|
||||||
<h1 className="ui-hero-title">{title}</h1>
|
<h1 className={`ui-hero-title ${getHeroTitleSizeClass(payload.titleSize)}`}>{title}</h1>
|
||||||
{subtitle && <p className="mx-auto max-w-2xl text-lg text-surface-card md:text-xl">{subtitle}</p>}
|
{subtitle && <p className="mx-auto max-w-2xl text-lg text-surface-card md:text-xl">{subtitle}</p>}
|
||||||
{(author || date) && (
|
{(author || date) && (
|
||||||
<p className="text-xs font-bold uppercase tracking-[0.22em] text-surface-card">
|
<p className="text-xs font-bold uppercase tracking-[0.22em] text-surface-card">
|
||||||
|
|||||||
@@ -652,6 +652,15 @@ export const DefaultTextColorSchemeSchema = (fallback: TextColorScheme = 'light'
|
|||||||
.optional()
|
.optional()
|
||||||
.transform((val) => (val ? (val as TextColorScheme) : fallback));
|
.transform((val) => (val ? (val as TextColorScheme) : fallback));
|
||||||
|
|
||||||
|
export const TitleSizeSchema = z.enum(['sm', 'md', 'lg', 'xl']);
|
||||||
|
export type TitleSize = z.infer<typeof TitleSizeSchema>;
|
||||||
|
|
||||||
|
export const DefaultTitleSizeSchema = (fallback: TitleSize = 'xl') =>
|
||||||
|
z
|
||||||
|
.union([TitleSizeSchema, z.literal(''), z.null()])
|
||||||
|
.optional()
|
||||||
|
.transform((val) => (val ? (val as TitleSize) : fallback));
|
||||||
|
|
||||||
export const SectionPaddingLevelSchema = z.enum(['none', 'compact', 'normal', 'spacious']);
|
export const SectionPaddingLevelSchema = z.enum(['none', 'compact', 'normal', 'spacious']);
|
||||||
export type SectionPaddingLevel = z.infer<typeof SectionPaddingLevelSchema>;
|
export type SectionPaddingLevel = z.infer<typeof SectionPaddingLevelSchema>;
|
||||||
|
|
||||||
@@ -674,6 +683,7 @@ export const HeroSectionPayloadSchema = z.object({
|
|||||||
mobileButtonPosition: OptionalContentPositionSchema,
|
mobileButtonPosition: OptionalContentPositionSchema,
|
||||||
contentWidth: DefaultContentWidthSchema('standard'),
|
contentWidth: DefaultContentWidthSchema('standard'),
|
||||||
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
||||||
|
titleSize: DefaultTitleSizeSchema('xl'),
|
||||||
overlayStyle: z.enum(['gradient', 'solid', 'none']).optional().default('gradient'),
|
overlayStyle: z.enum(['gradient', 'solid', 'none']).optional().default('gradient'),
|
||||||
overlayOpacity: z.number().min(0).max(100).optional(),
|
overlayOpacity: z.number().min(0).max(100).optional(),
|
||||||
});
|
});
|
||||||
@@ -712,6 +722,7 @@ export const BannerSectionPayloadSchema = z.object({
|
|||||||
mobileButtonPosition: OptionalContentPositionSchema,
|
mobileButtonPosition: OptionalContentPositionSchema,
|
||||||
contentWidth: DefaultContentWidthSchema('standard'),
|
contentWidth: DefaultContentWidthSchema('standard'),
|
||||||
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
||||||
|
titleSize: DefaultTitleSizeSchema('xl'),
|
||||||
});
|
});
|
||||||
export type BannerSectionPayload = z.infer<typeof BannerSectionPayloadSchema>;
|
export type BannerSectionPayload = z.infer<typeof BannerSectionPayloadSchema>;
|
||||||
|
|
||||||
@@ -803,6 +814,7 @@ export const HeroVideoSectionPayloadSchema = z.object({
|
|||||||
mobileButtonPosition: OptionalContentPositionSchema,
|
mobileButtonPosition: OptionalContentPositionSchema,
|
||||||
contentWidth: DefaultContentWidthSchema('standard'),
|
contentWidth: DefaultContentWidthSchema('standard'),
|
||||||
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
||||||
|
titleSize: DefaultTitleSizeSchema('xl'),
|
||||||
});
|
});
|
||||||
export type HeroVideoSectionPayload = z.infer<typeof HeroVideoSectionPayloadSchema>;
|
export type HeroVideoSectionPayload = z.infer<typeof HeroVideoSectionPayloadSchema>;
|
||||||
|
|
||||||
@@ -836,6 +848,7 @@ export const HeroCarouselSlideSchema = z.object({
|
|||||||
mobileButtonPosition: OptionalContentPositionSchema,
|
mobileButtonPosition: OptionalContentPositionSchema,
|
||||||
contentWidth: DefaultContentWidthSchema('standard'),
|
contentWidth: DefaultContentWidthSchema('standard'),
|
||||||
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
textColorScheme: DefaultTextColorSchemeSchema('light'),
|
||||||
|
titleSize: DefaultTitleSizeSchema('xl'),
|
||||||
});
|
});
|
||||||
export type HeroCarouselSlide = z.infer<typeof HeroCarouselSlideSchema>;
|
export type HeroCarouselSlide = z.infer<typeof HeroCarouselSlideSchema>;
|
||||||
|
|
||||||
@@ -889,6 +902,7 @@ export const HeroArticleSectionPayloadSchema = z.object({
|
|||||||
imageUrl: z.string().optional(),
|
imageUrl: z.string().optional(),
|
||||||
backgroundImageUrl: z.string().optional(),
|
backgroundImageUrl: z.string().optional(),
|
||||||
overlayColor: z.string().optional(),
|
overlayColor: z.string().optional(),
|
||||||
|
titleSize: DefaultTitleSizeSchema('xl'),
|
||||||
});
|
});
|
||||||
export type HeroArticleSectionPayload = z.infer<typeof HeroArticleSectionPayloadSchema>;
|
export type HeroArticleSectionPayload = z.infer<typeof HeroArticleSectionPayloadSchema>;
|
||||||
|
|
||||||
@@ -1189,6 +1203,7 @@ export const HeroV2SectionPayloadSchema = z.object({
|
|||||||
secondaryButtonText: LocalizedStringSchema.optional(),
|
secondaryButtonText: LocalizedStringSchema.optional(),
|
||||||
secondaryButtonLink: z.string().optional(),
|
secondaryButtonLink: z.string().optional(),
|
||||||
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
||||||
|
titleSize: DefaultTitleSizeSchema('lg'),
|
||||||
});
|
});
|
||||||
export type HeroV2SectionPayload = z.infer<typeof HeroV2SectionPayloadSchema>;
|
export type HeroV2SectionPayload = z.infer<typeof HeroV2SectionPayloadSchema>;
|
||||||
|
|
||||||
@@ -1215,6 +1230,7 @@ export const HeroMinimalSectionPayloadSchema = z.object({
|
|||||||
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
||||||
contentAlignment: z.enum(['left', 'center', 'right']).optional().default('center'),
|
contentAlignment: z.enum(['left', 'center', 'right']).optional().default('center'),
|
||||||
overlayOpacity: z.number().optional().default(20),
|
overlayOpacity: z.number().optional().default(20),
|
||||||
|
titleSize: DefaultTitleSizeSchema('lg'),
|
||||||
});
|
});
|
||||||
export type HeroMinimalSectionPayload = z.infer<typeof HeroMinimalSectionPayloadSchema>;
|
export type HeroMinimalSectionPayload = z.infer<typeof HeroMinimalSectionPayloadSchema>;
|
||||||
|
|
||||||
@@ -1225,6 +1241,7 @@ export const HeroSplitMinimalSectionPayloadSchema = z.object({
|
|||||||
imagePosition: z.enum(['left', 'right']).optional().default('right'),
|
imagePosition: z.enum(['left', 'right']).optional().default('right'),
|
||||||
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
||||||
backgroundColor: z.string().optional(),
|
backgroundColor: z.string().optional(),
|
||||||
|
titleSize: DefaultTitleSizeSchema('lg'),
|
||||||
});
|
});
|
||||||
export type HeroSplitMinimalSectionPayload = z.infer<typeof HeroSplitMinimalSectionPayloadSchema>;
|
export type HeroSplitMinimalSectionPayload = z.infer<typeof HeroSplitMinimalSectionPayloadSchema>;
|
||||||
|
|
||||||
@@ -1236,6 +1253,7 @@ export const HeroVideoMinimalSectionPayloadSchema = z.object({
|
|||||||
overlayOpacity: z.number().optional().default(25),
|
overlayOpacity: z.number().optional().default(25),
|
||||||
height: z.enum(['full', 'large', 'medium']).optional().default('large'),
|
height: z.enum(['full', 'large', 'medium']).optional().default('large'),
|
||||||
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
focalPoint: z.object({ x: z.string(), y: z.string() }).optional(),
|
||||||
|
titleSize: DefaultTitleSizeSchema('lg'),
|
||||||
});
|
});
|
||||||
export type HeroVideoMinimalSectionPayload = z.infer<typeof HeroVideoMinimalSectionPayloadSchema>;
|
export type HeroVideoMinimalSectionPayload = z.infer<typeof HeroVideoMinimalSectionPayloadSchema>;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user