Fix button roundtrip in editor, alignment persistence, and test email rendering
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
import React from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Section } from '../../store/usePageEditorStore';
|
||||
|
||||
|
||||
|
||||
interface ImageTextRendererProps {
|
||||
section: Section;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const COLOR_SCHEMES: Record<string, { bg: string; text: string }> = {
|
||||
default: { bg: '', text: 'text-gray-900' },
|
||||
primary: { bg: 'wn-primary-bg', text: 'text-white' },
|
||||
secondary: { bg: 'wn-secondary-bg', text: 'text-white' },
|
||||
muted: { bg: 'bg-gray-50', text: 'text-gray-700' },
|
||||
gradient: { bg: 'wn-gradient-bg', text: 'text-white' },
|
||||
};
|
||||
|
||||
export function ImageTextRenderer({ section, className }: ImageTextRendererProps) {
|
||||
const scheme = COLOR_SCHEMES[section.colorScheme || 'default'];
|
||||
const layout = section.layoutVariant || 'image-left';
|
||||
const isImageRight = layout === 'image-right';
|
||||
|
||||
const title = section.props?.title?.value || 'Section Title';
|
||||
const text = section.props?.text?.value || 'Your descriptive text goes here. Edit this section to add your own content.';
|
||||
const image = section.props?.image?.value;
|
||||
|
||||
const isDynamicTitle = section.props?.title?.type === 'dynamic';
|
||||
const isDynamicText = section.props?.text?.type === 'dynamic';
|
||||
const isDynamicImage = section.props?.image?.type === 'dynamic';
|
||||
|
||||
const cta_text = section.props?.cta_text?.value;
|
||||
const cta_url = section.props?.cta_url?.value;
|
||||
|
||||
// Helper to get text styles (including font family)
|
||||
const getTextStyles = (elementName: string) => {
|
||||
const styles = section.elementStyles?.[elementName] || {};
|
||||
return {
|
||||
classNames: cn(
|
||||
styles.fontSize,
|
||||
styles.fontWeight,
|
||||
{
|
||||
'font-sans': styles.fontFamily === 'secondary',
|
||||
'font-serif': styles.fontFamily === 'primary',
|
||||
}
|
||||
),
|
||||
style: {
|
||||
color: styles.color,
|
||||
textAlign: styles.textAlign,
|
||||
backgroundColor: styles.backgroundColor
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const titleStyle = getTextStyles('title');
|
||||
const textStyle = getTextStyles('text');
|
||||
const imageStyle = section.elementStyles?.['image'] || {};
|
||||
|
||||
const buttonStyle = getTextStyles('button');
|
||||
|
||||
// Helper to get background style for dynamic schemes
|
||||
const getBackgroundStyle = () => {
|
||||
if (scheme.bg === 'wn-gradient-bg') {
|
||||
return { backgroundImage: 'linear-gradient(135deg, var(--wn-gradient-start, #9333ea), var(--wn-gradient-end, #3b82f6))' };
|
||||
}
|
||||
if (scheme.bg === 'wn-primary-bg') {
|
||||
return { backgroundColor: 'var(--wn-primary, #1a1a1a)' };
|
||||
}
|
||||
if (scheme.bg === 'wn-secondary-bg') {
|
||||
return { backgroundColor: 'var(--wn-secondary, #6b7280)' };
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn('py-12 px-4 md:py-20 md:px-8', !scheme.bg.startsWith('wn-') && scheme.bg, scheme.text, className)}
|
||||
style={getBackgroundStyle()}
|
||||
>
|
||||
<div className={cn(
|
||||
'max-w-6xl mx-auto flex items-center gap-12',
|
||||
isImageRight ? 'flex-col md:flex-row-reverse' : 'flex-col md:flex-row',
|
||||
'flex-wrap md:flex-nowrap'
|
||||
)}>
|
||||
{/* Image */}
|
||||
<div className="w-full md:w-1/2" style={{ backgroundColor: imageStyle.backgroundColor }}>
|
||||
{image ? (
|
||||
<img
|
||||
src={image}
|
||||
alt={title}
|
||||
className="w-full h-auto rounded-xl shadow-lg"
|
||||
style={{
|
||||
objectFit: imageStyle.objectFit,
|
||||
width: imageStyle.width,
|
||||
maxWidth: '100%',
|
||||
height: imageStyle.height,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-64 md:h-80 bg-gray-200 rounded-xl flex items-center justify-center">
|
||||
<span className="text-gray-400">
|
||||
{isDynamicImage ? (
|
||||
<span className="flex items-center gap-2">
|
||||
<span className="text-orange-400">◆</span>
|
||||
{section.props?.image?.source}
|
||||
</span>
|
||||
) : (
|
||||
'Add Image'
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="w-full md:w-1/2 space-y-4">
|
||||
<h2
|
||||
className={cn(
|
||||
"text-2xl md:text-3xl font-bold",
|
||||
titleStyle.classNames
|
||||
)}
|
||||
style={titleStyle.style}
|
||||
>
|
||||
{isDynamicTitle && <span className="text-orange-400 mr-2">◆</span>}
|
||||
{title}
|
||||
</h2>
|
||||
<p
|
||||
className={cn(
|
||||
"text-lg opacity-90 leading-relaxed",
|
||||
textStyle.classNames
|
||||
)}
|
||||
style={textStyle.style}
|
||||
>
|
||||
{isDynamicText && <span className="text-orange-400 mr-2">◆</span>}
|
||||
{text}
|
||||
</p>
|
||||
|
||||
{cta_text && cta_url && (
|
||||
<div className="pt-4">
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2",
|
||||
!buttonStyle.style?.backgroundColor && "bg-blue-600",
|
||||
!buttonStyle.style?.color && "text-white",
|
||||
buttonStyle.classNames
|
||||
)}
|
||||
style={buttonStyle.style}
|
||||
>
|
||||
{cta_text}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user