This commit is contained in:
Your Name committed 2026-07-14 07:30:16 -04:00
1 parent 752451b1d4
commit f6c188bd93
5 files changed
+27 -3

No files matched your search

@@ -1,12 +1,13 @@
import { UploadCloud, Image as ImageIcon } from 'lucide-react';
import { type PageSection } from '@homaroma/types';
import FocalPointPicker from './FocalPointPicker';
interface BannerFormProps {
editingSection: Partial<PageSection>;
editingLang: string;
getLocalizedValue: (payload: any, field: string) => string;
updateLocalizedValue: (field: string, value: string) => void;
updatePayloadValue: (field: string, value: string | number) => void;
updatePayloadValue: (field: string, value: any) => void;
setUploadTarget: (target: { type: 'main' | 'slide'; index?: number } | null) => void;
setIsMediaModalOpen: (open: boolean) => void;
}
@@ -47,6 +48,16 @@ export default function BannerForm({
</div>
</div>
{editingSection.payload?.imageUrl && (
<div className="md:col-span-2">
<FocalPointPicker
imageUrl={editingSection.payload.imageUrl}
focalPoint={editingSection.payload.focalPoint}
onChange={(focalPoint) => updatePayloadValue('focalPoint', focalPoint)}
/>
</div>
)}
<div className="space-y-2">
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">Banner Title</label>
<input
+1 -1
View File
@@ -57,7 +57,7 @@ const ADD_PAGE_SECTION_GUIDANCE: Record<string, { required: string[]; example: s
},
BANNER: {
required: ["imageUrl"],
example: `{ "imageUrl": "https://example.com/banner.jpg", "title": ${localizedStringExample}, "buttonText": ${localizedStringExample} }`
example: `{ "imageUrl": "https://example.com/banner.jpg", "title": ${localizedStringExample}, "buttonText": ${localizedStringExample}, "focalPoint": { "x": "50%", "y": "50%" } }`
},
HERO_ARTICLE: {
required: ["title"],
@@ -14,6 +14,8 @@ export default function DynamicBanner({ payload }: DynamicBannerProps) {
const title = getLocalizedField(payload.title, lang);
const description = getLocalizedField(payload.description, lang);
const buttonText = getLocalizedField(payload.buttonText, lang);
const focalPoint = typeof payload.focalPoint === 'object' && payload.focalPoint ? payload.focalPoint : undefined;
const imageStyle = focalPoint ? { objectPosition: `${focalPoint.x} ${focalPoint.y}` } : undefined;
return (
<section className="ui-section-band bg-pop-bg relative overflow-hidden">
@@ -24,6 +26,7 @@ export default function DynamicBanner({ payload }: DynamicBannerProps) {
src={imageUrl}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-[1.03]"
alt={title || "Banner"}
style={imageStyle}
/>
<div className="ui-banner-overlay"></div>
</div>
@@ -55,6 +58,7 @@ export default function DynamicBanner({ payload }: DynamicBannerProps) {
src={imageUrl}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-[1.03]"
alt={title || "Banner"}
style={imageStyle}
/>
<div className="ui-banner-overlay"></div>
</div>
@@ -424,10 +424,18 @@ function BannerSection({ payload, lang }: { payload: Record<string, unknown>, la
const buttonText = localizedFromRecord(payload, 'buttonText', resolvedLang)
const imageUrl = typeof payload.imageUrl === 'string' ? payload.imageUrl : '/images/hero.png'
const linkUrl = typeof payload.linkUrl === 'string' ? payload.linkUrl : ''
const focalPoint = typeof payload.focalPoint === 'object' && payload.focalPoint ? (payload.focalPoint as { x: string, y: string }) : undefined
const content = (
<div className="ui-banner-shell">
<Image src={imageUrl} alt={title || 'Banner'} fill unoptimized className="absolute inset-0 h-full w-full object-cover" />
<Image
src={imageUrl}
alt={title || 'Banner'}
fill
unoptimized
className="absolute inset-0 h-full w-full object-cover"
style={{ objectPosition: focalPoint ? `${focalPoint.x} ${focalPoint.y}` : undefined }}
/>
<div className="ui-banner-overlay" />
<div className="ui-banner-content">
{title && <h2 className="text-3xl font-semibold text-brand-primary drop-shadow-md md:text-5xl">{title}</h2>}