'use client' import { useCallback } from 'react' import { Block, TextBlock, DividerBlock, CTABlock, ImageBlock, SpacerBlock, SocialBlock, HeaderBlock, FooterBlock, SocialLink, BlockStyle, } from '../types' import { Button } from '../../ui/button' import { Input } from '../../ui/input' import { Label } from '../../ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../ui/select' import { Plus, Trash2 } from 'lucide-react' interface BlockPropertyPanelProps { block: Block onChange: (block: Block) => void } export function BlockPropertyPanel({ block, onChange }: BlockPropertyPanelProps) { const updateStyle = useCallback( (updates: Partial) => { onChange({ ...block, style: { ...block.style, ...updates } }) }, [block, onChange] ) return (
{block.type} Settings
{/* Type-specific settings */} {block.type === 'text' && ( onChange(b)} /> )} {block.type === 'divider' && ( onChange(b)} /> )} {block.type === 'cta' && ( onChange(b)} /> )} {block.type === 'image' && ( onChange(b)} /> )} {block.type === 'spacer' && ( onChange(b)} /> )} {block.type === 'social' && ( onChange(b)} /> )} {block.type === 'header' && ( onChange(b)} /> )} {block.type === 'footer' && ( onChange(b)} /> )} {/* Common: spacing/background */}
Spacing
updateStyle({ paddingTop: parseInt(e.target.value) || 0 })} className="h-8 text-xs" />
updateStyle({ paddingBottom: parseInt(e.target.value) || 0 })} className="h-8 text-xs" />
updateStyle({ backgroundColor: e.target.value })} className="h-8 w-8 rounded border cursor-pointer" /> updateStyle({ backgroundColor: e.target.value })} placeholder="transparent" className="h-8 text-xs" />
) } // --- Text settings --- function TextSettings({ block, onChange }: { block: TextBlock; onChange: (b: TextBlock) => void }) { return (
onChange({ ...block, fontSize: parseInt(e.target.value) || 16 })} className="h-8 text-xs" />
onChange({ ...block, lineHeight: parseFloat(e.target.value) || 1.6 })} className="h-8 text-xs" />
onChange({ ...block, textColor: e.target.value })} className="h-8 w-8 rounded border cursor-pointer" /> onChange({ ...block, textColor: e.target.value })} className="h-8 text-xs" />
) } // --- Divider settings --- function DividerSettings({ block, onChange }: { block: DividerBlock; onChange: (b: DividerBlock) => void }) { return (
onChange({ ...block, color: e.target.value })} className="h-8 w-8 rounded border cursor-pointer" /> onChange({ ...block, color: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, thickness: parseInt(e.target.value) || 1 })} className="h-8 text-xs" min={1} max={10} />
onChange({ ...block, width: parseInt(e.target.value) || 100 })} className="h-8 text-xs" min={10} max={100} />
) } // --- Button settings --- function ButtonSettings({ block, onChange }: { block: CTABlock; onChange: (b: CTABlock) => void }) { return (
onChange({ ...block, text: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, url: e.target.value })} placeholder="https://..." className="h-8 text-xs" />
onChange({ ...block, buttonColor: e.target.value })} className="h-8 w-8 rounded border cursor-pointer" /> onChange({ ...block, buttonColor: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, textColor: e.target.value })} className="h-8 w-8 rounded border cursor-pointer" /> onChange({ ...block, textColor: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, borderRadius: parseInt(e.target.value) || 0 })} className="h-8 text-xs" min={0} max={50} />
onChange({ ...block, paddingH: parseInt(e.target.value) || 0 })} className="h-8 text-xs" />
onChange({ ...block, paddingV: parseInt(e.target.value) || 0 })} className="h-8 text-xs" />
) } // --- Image settings --- function ImageSettings({ block, onChange }: { block: ImageBlock; onChange: (b: ImageBlock) => void }) { return (
onChange({ ...block, url: e.target.value })} placeholder="https://..." className="h-8 text-xs" />
onChange({ ...block, alt: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, caption: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, linkUrl: e.target.value })} placeholder="https://..." className="h-8 text-xs" />
onChange({ ...block, width: parseInt(e.target.value) || 100 })} className="h-8 text-xs" min={10} max={100} />
) } // --- Spacer settings --- function SpacerSettings({ block, onChange }: { block: SpacerBlock; onChange: (b: SpacerBlock) => void }) { return (
onChange({ ...block, height: parseInt(e.target.value) || 8 })} className="h-8 text-xs" min={8} max={200} />
) } // --- Social settings --- function SocialSettings({ block, onChange }: { block: SocialBlock; onChange: (b: SocialBlock) => void }) { const addLink = () => { const link: SocialLink = { id: `social-${Date.now()}`, platform: 'website', url: '', } onChange({ ...block, links: [...block.links, link] }) } const removeLink = (id: string) => { onChange({ ...block, links: block.links.filter((l) => l.id !== id) }) } const updateLink = (id: string, updates: Partial) => { onChange({ ...block, links: block.links.map((l) => (l.id === id ? { ...l, ...updates } : l)), }) } const platforms: SocialLink['platform'][] = [ 'linkedin', 'twitter', 'facebook', 'instagram', 'youtube', 'github', 'website', ] return (
onChange({ ...block, iconSize: parseInt(e.target.value) || 24 })} className="h-8 text-xs" min={16} max={48} />
{block.links.map((link) => (
updateLink(link.id, { url: e.target.value })} placeholder="URL" className="h-7 text-xs" />
))}
) } // --- Header settings --- function HeaderSettings({ block, onChange }: { block: HeaderBlock; onChange: (b: HeaderBlock) => void }) { return (
onChange({ ...block, companyName: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, logoUrl: e.target.value })} placeholder="https://..." className="h-8 text-xs" />
) } // --- Footer settings --- function FooterSettings({ block, onChange }: { block: FooterBlock; onChange: (b: FooterBlock) => void }) { return (
onChange({ ...block, companyName: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, address: e.target.value })} className="h-8 text-xs" />
onChange({ ...block, showUnsubscribe: e.target.checked })} className="rounded" id="show-unsub" />
{block.showUnsubscribe && (
onChange({ ...block, unsubscribeUrl: e.target.value })} placeholder="https://..." className="h-8 text-xs" />
)}
) }