From 943fd8f1a364f336d423853201de5a9a9d0743a3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 10 Oct 2026 06:15:48 +0700 Subject: [PATCH] x --- .../components/page-builder/BannerForm.tsx | 2 + .../page-builder/ContentPositionPicker.tsx | 50 +++++++++++++++- .../page-builder/HeroArticleForm.tsx | 14 +++++ .../src/components/page-builder/HeroForm.tsx | 2 + .../components/page-builder/HeroV2Form.tsx | 14 +++++ .../components/page-builder/HeroVideoForm.tsx | 2 + .../src/lib/productDetailSections.test.ts | 4 ++ apps/backend/src/routes/pages.ts | 2 +- apps/mcp-server/section-toolkit.ts | 8 +-- apps/spa/src/components/DynamicHero.tsx | 21 ++++++- apps/spa/src/components/DynamicHeroV2.tsx | 3 +- apps/spa/src/components/DynamicHeroVideo.tsx | 9 ++- apps/spa/src/index.css | 16 +++++ apps/website/src/app/globals.css | 60 +++++++++++++++++++ .../dynamic/DynamicPageRenderer.tsx | 52 +++++++++++++--- packages/types/index.ts | 18 ++++++ 16 files changed, 257 insertions(+), 20 deletions(-) diff --git a/apps/admin/src/components/page-builder/BannerForm.tsx b/apps/admin/src/components/page-builder/BannerForm.tsx index 52550a6..960b91b 100644 --- a/apps/admin/src/components/page-builder/BannerForm.tsx +++ b/apps/admin/src/components/page-builder/BannerForm.tsx @@ -110,6 +110,8 @@ export default function BannerForm({ onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)} textColorScheme={editingSection.payload?.textColorScheme} onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)} + titleSize={editingSection.payload?.titleSize} + onChangeTitleSize={(size) => updatePayloadValue('titleSize', size)} /> diff --git a/apps/admin/src/components/page-builder/ContentPositionPicker.tsx b/apps/admin/src/components/page-builder/ContentPositionPicker.tsx index 06128cc..9dfd0ef 100644 --- a/apps/admin/src/components/page-builder/ContentPositionPicker.tsx +++ b/apps/admin/src/components/page-builder/ContentPositionPicker.tsx @@ -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 = [ { 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' }, ] 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 = [ { id: 'light', @@ -45,6 +52,8 @@ export interface ContentPositionPickerProps { onChangeContentWidth?: (width: string) => void; textColorScheme?: 'light' | 'dark' | string; onChangeTextColorScheme?: (scheme: 'light' | 'dark') => void; + titleSize?: 'sm' | 'md' | 'lg' | 'xl' | string; + onChangeTitleSize?: (size: string) => void; title?: string; subtitle?: string; compact?: boolean; @@ -60,6 +69,8 @@ export default function ContentPositionPicker({ onChangeContentWidth, textColorScheme, onChangeTextColorScheme, + titleSize, + onChangeTitleSize, title = 'ตำแหน่งปุ่ม & เนื้อหา (Button & Content Position)', subtitle = 'สามารถแยกตำแหน่งระหว่าง Desktop (PC) และ Mobile (มือถือ) ได้อิสระ', compact = false, @@ -255,6 +266,43 @@ export default function ContentPositionPicker({ )} + + {/* Title Size / Heading Scale Preset Selection */} + {onChangeTitleSize && ( +
+
+ + + ขนาดตัวอักษรหัวข้อ (Title Font Size Preset) + + + {(titleSize || 'xl').toUpperCase()} + +
+
+ {TITLE_SIZE_OPTIONS.map((opt) => { + const isSelected = (titleSize || 'xl') === opt.id; + return ( + + ); + })} +
+
+ )} ); } diff --git a/apps/admin/src/components/page-builder/HeroArticleForm.tsx b/apps/admin/src/components/page-builder/HeroArticleForm.tsx index d3505bd..ac1554d 100644 --- a/apps/admin/src/components/page-builder/HeroArticleForm.tsx +++ b/apps/admin/src/components/page-builder/HeroArticleForm.tsx @@ -72,6 +72,20 @@ export default function HeroArticleForm({ /> +
+ + +
+
updatePayloadValue('contentWidth', w)} textColorScheme={editingSection.payload?.textColorScheme} onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)} + titleSize={editingSection.payload?.titleSize} + onChangeTitleSize={(size) => updatePayloadValue('titleSize', size)} />
diff --git a/apps/admin/src/components/page-builder/HeroV2Form.tsx b/apps/admin/src/components/page-builder/HeroV2Form.tsx index e5042ee..fba2e5b 100644 --- a/apps/admin/src/components/page-builder/HeroV2Form.tsx +++ b/apps/admin/src/components/page-builder/HeroV2Form.tsx @@ -71,6 +71,20 @@ export default function HeroV2Form({ +
+ + +
+
updatePayloadValue('contentWidth', w)} textColorScheme={payload.textColorScheme} onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)} + titleSize={payload.titleSize} + onChangeTitleSize={(size) => updatePayloadValue('titleSize', size)} />
); diff --git a/apps/backend/src/lib/productDetailSections.test.ts b/apps/backend/src/lib/productDetailSections.test.ts index 2e4c420..d74d547 100644 --- a/apps/backend/src/lib/productDetailSections.test.ts +++ b/apps/backend/src/lib/productDetailSections.test.ts @@ -17,6 +17,10 @@ const validHeroCarouselPayload = { subtitle: { th: "ข้อความรอง", en: "Supporting copy" }, buttonText: { th: "ดูสินค้า", en: "View product" }, focalPoint: { x: "50%", y: "45%" }, + buttonPosition: "bottom-left", + contentWidth: "standard", + textColorScheme: "light", + titleSize: "xl", }, ], autoplay: true, diff --git a/apps/backend/src/routes/pages.ts b/apps/backend/src/routes/pages.ts index ac7b1b4..b46ab84 100644 --- a/apps/backend/src/routes/pages.ts +++ b/apps/backend/src/routes/pages.ts @@ -1,6 +1,6 @@ import { Elysia, t } from "elysia"; 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 { LocalizedStringSchema, HeroSectionPayloadSchema, diff --git a/apps/mcp-server/section-toolkit.ts b/apps/mcp-server/section-toolkit.ts index 8fb1f6a..47591f2 100644 --- a/apps/mcp-server/section-toolkit.ts +++ b/apps/mcp-server/section-toolkit.ts @@ -89,8 +89,8 @@ const PAGE_BLOCK_METADATA: Record = { HERO: { type: "HERO", requiredFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink"], - optionalFields: ["focalPoint"], - renderedFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink", "focalPoint"], + optionalFields: ["focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize"], + renderedFields: ["tagline", "title", "description", "imageUrl", "buttonText", "buttonLink", "focalPoint", "contentWidth", "textColorScheme", "buttonPosition", "mobileButtonPosition", "overlayStyle", "overlayOpacity", "titleSize"], storedOnlyFields: [], discoveryToolsNeeded: [], warnings: ["Use an image URL from a host allowed by apps/website next.config.ts."], @@ -669,8 +669,8 @@ const PAGE_BLOCK_METADATA: Record = { HERO_V2: { type: "HERO_V2", requiredFields: ["title", "imageUrl"], - optionalFields: ["tagline", "description", "contentAlignment", "showOrnament", "primaryButtonText", "primaryButtonLink", "secondaryButtonText", "secondaryButtonLink", "focalPoint"], - renderedFields: ["tagline", "title", "description", "imageUrl", "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", "titleSize"], storedOnlyFields: [], discoveryToolsNeeded: [], warnings: ["contentAlignment must be left, center, or right. Use an image URL allowed by apps/website."], diff --git a/apps/spa/src/components/DynamicHero.tsx b/apps/spa/src/components/DynamicHero.tsx index a19cfe4..d2a1b06 100644 --- a/apps/spa/src/components/DynamicHero.tsx +++ b/apps/spa/src/components/DynamicHero.tsx @@ -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) { const { t, i18n } = useTranslation(); const lang = i18n.language; @@ -240,6 +254,9 @@ export default function DynamicHero({ payload }: DynamicHeroProps) { }; 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 (
@@ -258,14 +275,14 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
-
+
{tagline && (

{tagline}

)} {title && ( -

+

{renderTitle(title)}

)} diff --git a/apps/spa/src/components/DynamicHeroV2.tsx b/apps/spa/src/components/DynamicHeroV2.tsx index f1fa506..25e3d47 100644 --- a/apps/spa/src/components/DynamicHeroV2.tsx +++ b/apps/spa/src/components/DynamicHeroV2.tsx @@ -2,6 +2,7 @@ import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { getLocalizedField } from '../utils/localization'; import { Sparkles, ChevronRight } from 'lucide-react'; +import { getHeroTitleSizeClass } from './DynamicHero'; interface DynamicHeroV2Props { payload: Record; @@ -68,7 +69,7 @@ export default function DynamicHeroV2({ payload }: DynamicHeroV2Props) {
)} -

+

{renderTitle(title || '')}

diff --git a/apps/spa/src/components/DynamicHeroVideo.tsx b/apps/spa/src/components/DynamicHeroVideo.tsx index e351d82..227985d 100644 --- a/apps/spa/src/components/DynamicHeroVideo.tsx +++ b/apps/spa/src/components/DynamicHeroVideo.tsx @@ -2,7 +2,7 @@ import { Link } from 'react-router-dom'; import type { HeroVideoSectionPayload } from '@homaroma/types'; import { useTranslation } from 'react-i18next'; import { getLocalizedField } from '../utils/localization'; -import { getHeroPositionClasses, getHeroContainerWidthClasses } from './DynamicHero'; +import { getHeroPositionClasses, getHeroContainerWidthClasses, getHeroTitleSizeClass } from './DynamicHero'; interface DynamicHeroVideoProps { payload: HeroVideoSectionPayload; @@ -98,6 +98,9 @@ export default function DynamicHeroVideo({ payload }: DynamicHeroVideoProps) { const desktopPosition = (payload as any).buttonPosition || 'center'; const mobilePosition = (payload as any).mobileButtonPosition || desktopPosition; 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 containerClasses = getHeroContainerWidthClasses(contentWidth); @@ -109,14 +112,14 @@ export default function DynamicHeroVideo({ payload }: DynamicHeroVideoProps) { >
-
+
{tagline && (

{tagline}

)} -

+

{renderTitle(title) || renderTitle(t('hero.defaultTitle'))}

diff --git a/apps/spa/src/index.css b/apps/spa/src/index.css index f3cad84..d44f441 100644 --- a/apps/spa/src/index.css +++ b/apps/spa/src/index.css @@ -148,6 +148,22 @@ 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 { @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); diff --git a/apps/website/src/app/globals.css b/apps/website/src/app/globals.css index bf77f42..3b3b1fb 100644 --- a/apps/website/src/app/globals.css +++ b/apps/website/src/app/globals.css @@ -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)); } + .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 { margin-inline: auto; max-width: 42rem; @@ -568,6 +588,26 @@ 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 { font-size: 1.25rem; line-height: 1.75rem; @@ -588,6 +628,26 @@ font-size: 6rem; 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 { diff --git a/apps/website/src/components/dynamic/DynamicPageRenderer.tsx b/apps/website/src/components/dynamic/DynamicPageRenderer.tsx index fd4ac77..c30e0b9 100644 --- a/apps/website/src/components/dynamic/DynamicPageRenderer.tsx +++ b/apps/website/src/components/dynamic/DynamicPageRenderer.tsx @@ -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, lang: string }) { const { t } = useTranslation() const i18nLang = useLang() @@ -288,6 +317,9 @@ function HeroSection({ payload, lang }: { payload: Record, lang const contentWidth = typeof payload.contentWidth === 'string' ? payload.contentWidth : 'standard' const textColorScheme = typeof payload.textColorScheme === 'string' ? payload.textColorScheme : 'light' 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 // If fields are explicitly defined as empty strings, respect them as empty @@ -357,14 +389,14 @@ function HeroSection({ payload, lang }: { payload: Record, lang {renderOverlay()}
-
+
{tagline && (

{tagline}

)} {title && ( -

+

{renderAccentTitle(title, isDarkText ? 'text-brand-primary font-medium' : 'ui-accent-text font-medium')}

)} @@ -607,14 +639,14 @@ function HeroVideoSection({ payload, lang }: { payload: Record,
-
+
{tagline && (

{tagline}

)} {title && ( -

+

{renderAccentTitle(title, isDarkText ? 'text-brand-primary font-medium' : undefined)}

)} @@ -1012,7 +1044,7 @@ function HeroV2Section({ payload, lang }: { payload: Record, la
)} -

+

{renderAccentTitle(title || '', 'text-brand-primary')}

@@ -1271,8 +1303,12 @@ function BannerSection({ payload, lang }: { payload: Record, la style={{ objectPosition: focalPoint ? `${focalPoint.x} ${focalPoint.y}` : undefined }} />
-
- {title &&

{title}

} +
+ {title && ( +

+ {title} +

+ )} {description &&

{description}

} {buttonText && (
@@ -2180,7 +2216,7 @@ function HeroArticleSection({ payload, lang }: { payload: Record {category &&

{category}

} -

{title}

+

{title}

{subtitle &&

{subtitle}

} {(author || date) && (

diff --git a/packages/types/index.ts b/packages/types/index.ts index 6d4d8ec..afae778 100644 --- a/packages/types/index.ts +++ b/packages/types/index.ts @@ -652,6 +652,15 @@ export const DefaultTextColorSchemeSchema = (fallback: TextColorScheme = 'light' .optional() .transform((val) => (val ? (val as TextColorScheme) : fallback)); +export const TitleSizeSchema = z.enum(['sm', 'md', 'lg', 'xl']); +export type TitleSize = z.infer; + +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 type SectionPaddingLevel = z.infer; @@ -674,6 +683,7 @@ export const HeroSectionPayloadSchema = z.object({ mobileButtonPosition: OptionalContentPositionSchema, contentWidth: DefaultContentWidthSchema('standard'), textColorScheme: DefaultTextColorSchemeSchema('light'), + titleSize: DefaultTitleSizeSchema('xl'), overlayStyle: z.enum(['gradient', 'solid', 'none']).optional().default('gradient'), overlayOpacity: z.number().min(0).max(100).optional(), }); @@ -712,6 +722,7 @@ export const BannerSectionPayloadSchema = z.object({ mobileButtonPosition: OptionalContentPositionSchema, contentWidth: DefaultContentWidthSchema('standard'), textColorScheme: DefaultTextColorSchemeSchema('light'), + titleSize: DefaultTitleSizeSchema('xl'), }); export type BannerSectionPayload = z.infer; @@ -803,6 +814,7 @@ export const HeroVideoSectionPayloadSchema = z.object({ mobileButtonPosition: OptionalContentPositionSchema, contentWidth: DefaultContentWidthSchema('standard'), textColorScheme: DefaultTextColorSchemeSchema('light'), + titleSize: DefaultTitleSizeSchema('xl'), }); export type HeroVideoSectionPayload = z.infer; @@ -836,6 +848,7 @@ export const HeroCarouselSlideSchema = z.object({ mobileButtonPosition: OptionalContentPositionSchema, contentWidth: DefaultContentWidthSchema('standard'), textColorScheme: DefaultTextColorSchemeSchema('light'), + titleSize: DefaultTitleSizeSchema('xl'), }); export type HeroCarouselSlide = z.infer; @@ -889,6 +902,7 @@ export const HeroArticleSectionPayloadSchema = z.object({ imageUrl: z.string().optional(), backgroundImageUrl: z.string().optional(), overlayColor: z.string().optional(), + titleSize: DefaultTitleSizeSchema('xl'), }); export type HeroArticleSectionPayload = z.infer; @@ -1189,6 +1203,7 @@ export const HeroV2SectionPayloadSchema = z.object({ secondaryButtonText: LocalizedStringSchema.optional(), secondaryButtonLink: z.string().optional(), focalPoint: z.object({ x: z.string(), y: z.string() }).optional(), + titleSize: DefaultTitleSizeSchema('lg'), }); export type HeroV2SectionPayload = z.infer; @@ -1215,6 +1230,7 @@ export const HeroMinimalSectionPayloadSchema = z.object({ focalPoint: z.object({ x: z.string(), y: z.string() }).optional(), contentAlignment: z.enum(['left', 'center', 'right']).optional().default('center'), overlayOpacity: z.number().optional().default(20), + titleSize: DefaultTitleSizeSchema('lg'), }); export type HeroMinimalSectionPayload = z.infer; @@ -1225,6 +1241,7 @@ export const HeroSplitMinimalSectionPayloadSchema = z.object({ imagePosition: z.enum(['left', 'right']).optional().default('right'), focalPoint: z.object({ x: z.string(), y: z.string() }).optional(), backgroundColor: z.string().optional(), + titleSize: DefaultTitleSizeSchema('lg'), }); export type HeroSplitMinimalSectionPayload = z.infer; @@ -1236,6 +1253,7 @@ export const HeroVideoMinimalSectionPayloadSchema = z.object({ overlayOpacity: z.number().optional().default(25), height: z.enum(['full', 'large', 'medium']).optional().default('large'), focalPoint: z.object({ x: z.string(), y: z.string() }).optional(), + titleSize: DefaultTitleSizeSchema('lg'), }); export type HeroVideoMinimalSectionPayload = z.infer;