import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Switch } from "@/components/ui/switch" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Textarea } from "@/components/ui/textarea" import { TemplateGrid, Template } from "@/components/ui/template-grid" import { LivePreview as LivePreviewContainer } from "@/components/ui/live-preview" import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible" import { GlobalColorPicker, resolveGlobalColor } from "@/components/ui/global-color-picker" import { GlobalTypographyPicker } from "@/components/ui/global-typography-picker" import { StyleSettings, FormSettings } from "../../types" import { Palette, FileText, LayoutTemplate, Bell, Square, MousePointer, RectangleHorizontal, ChevronDown, Minus, Plus, Layout, Type } from "lucide-react" import { useState, type CSSProperties } from "react" import { usePro } from "@/contexts/pro-context" import { ProIndicator } from "@/components/pro/pro-indicator" type FormDesignType = StyleSettings['formDesign'] interface CustomizationTabProps { styleSettings: StyleSettings formSettings: FormSettings updateStyleSettings: (key: K, value: StyleSettings[K]) => void updateFormSettings: (key: K, value: FormSettings[K]) => void } // Template configurations with metadata interface StylePreset { id: FormDesignType name: string description: string config: Omit } const stylePresets: StylePreset[] = [ { id: 'modern-minimal', name: 'Modern Minimal', description: 'Clean inline form', config: { primaryColor: '#00226b', textColor: '#1f2937', backgroundColor: '#f3f4f6', borderRadius: 8, buttonStyle: 'filled', formLayout: 'inline', contentAlignment: 'left', showIcon: false, padding: 20, margin: 16, borderWidth: 1, borderColor: '#e5e7eb', boxShadow: 'none', iconBackgroundColor: '#00226b', iconColor: '#ffffff', iconBorderRadius: 50, iconSize: 20, buttonTextColor: '#ffffff', buttonBorderColor: '', buttonBorderWidth: 1, buttonBorderRadius: 8, buttonPadding: 12, inputBorderColor: '#d1d5db', inputBorderWidth: 1, inputBackgroundColor: '#ffffff', inputTextColor: '#1f2937', inputBorderRadius: 8, fontFamily: '', }, }, { id: 'classic-card', name: 'Classic Card', description: 'Stacked card with bell', config: { primaryColor: '#00226b', textColor: '#1f2937', backgroundColor: '#f3f4f6', borderRadius: 12, buttonStyle: 'filled', formLayout: 'stacked', contentAlignment: 'center', showIcon: true, padding: 24, margin: 16, borderWidth: 0, borderColor: '#e5e7eb', boxShadow: 'small', iconBackgroundColor: '#00226b', iconColor: '#ffffff', iconBorderRadius: 50, iconSize: 20, buttonTextColor: '#ffffff', buttonBorderColor: '', buttonBorderWidth: 1, buttonBorderRadius: 8, buttonPadding: 12, inputBorderColor: '#d1d5db', inputBorderWidth: 1, inputBackgroundColor: '#ffffff', inputTextColor: '#1f2937', inputBorderRadius: 8, fontFamily: '', }, }, ] // Form Preview Component function FormPreview({ styleSettings, formSettings }: { styleSettings: StyleSettings formSettings: FormSettings }) { const isStacked = styleSettings.formLayout === 'stacked' const primaryColor = resolveGlobalColor(styleSettings.primaryColor, 'primary', '#00226b') const textColor = resolveGlobalColor(styleSettings.textColor, 'text', '#1f2937') const backgroundColor = resolveGlobalColor(styleSettings.backgroundColor, 'background', '#f3f4f6') const buttonBorderColor = styleSettings.buttonBorderColor || primaryColor const shadowBySize: Record = { none: 'none', small: '0 2px 6px rgb(3 7 18 / 0.1)', medium: '0 8px 16px rgb(3 7 18 / 0.14)', } const boxShadow = shadowBySize[styleSettings.boxShadow] const alignedEdge: Record = { left: 'flex-start', center: 'center', right: 'flex-end', } const containerStyle: CSSProperties = { color: textColor, background: backgroundColor, borderRadius: `${styleSettings.borderRadius}px`, padding: `${styleSettings.padding}px`, margin: `${styleSettings.margin}px`, borderStyle: 'solid', borderWidth: `${styleSettings.borderWidth}px`, borderColor: styleSettings.borderColor, boxShadow, fontFamily: styleSettings.fontFamily || 'inherit', textAlign: styleSettings.contentAlignment, } return (
{styleSettings.showIcon && (
)}

{formSettings.formTitle || 'Get Notified When Available'}

) } /** Compact number input with +/- buttons — replaces Slider */ function NumberStepper({ label, value, onChange, min, max, step = 1, unit = 'px', }: { label: string value: number onChange: (v: number) => void min: number max: number step?: number unit?: string }) { const clamp = (v: number) => Math.min(max, Math.max(min, v)) return (
{label && }
{ const parsed = parseInt(e.target.value, 10) if (!isNaN(parsed)) onChange(clamp(parsed)) }} className="h-8 w-14 text-center text-sm border-x bg-transparent outline-none" />
) } export function CustomizationTab({ styleSettings, formSettings, updateStyleSettings, updateFormSettings, }: CustomizationTabProps) { const { isPro } = usePro() // Accordion state for custom styling sections const [expandedSections, setExpandedSections] = useState>({ layout: false, colors: true, typography: false, containerStyling: false, iconStyling: false, buttonStyling: false, inputStyling: false, formContent: false, }) const toggleSection = (key: string) => { setExpandedSections(prev => ({ ...prev, [key]: !prev[key] })) } const templates: Template[] = [ ...stylePresets.map(preset => ({ id: preset.id, name: preset.name, description: preset.description, })), { id: 'custom', name: 'Custom', description: 'Build your own style', icon: Palette, isPro: true, alwaysVisible: true, }, ] // Apply a preset template const applyPreset = (presetId: string) => { updateStyleSettings('formDesign', presetId as FormDesignType) const preset = stylePresets.find(p => p.id === presetId) if (preset) { Object.entries(preset.config).forEach(([key, value]) => { if (value !== undefined) { updateStyleSettings(key as keyof StyleSettings, value as StyleSettings[keyof StyleSettings]) } }) } } return (
{/* Left Column - Templates + Settings */}
{/* Template Selection */} Templates Choose a pre-designed style for your notification form Customize Design {isPro ? 'Fine-tune every aspect of your form design' : 'Customize the colors of your form design'} {/* Colors — always available for brand matching */} toggleSection('colors')}> Colors
updateStyleSettings('primaryColor', v)} globalTokenId="primary" featureDefault="#00226b" /> updateStyleSettings('textColor', v)} globalTokenId="text" featureDefault="#1f2937" /> updateStyleSettings('backgroundColor', v)} globalTokenId="background" featureDefault="#f3f4f6" fullWidth />
{!isPro && (

For full customization control including layout, typography, spacing, borders, icons, buttons, and input fields, upgrade to Swift Commerce Pro.

)} {/* Layout & Display — Pro */} {isPro && ( toggleSection('layout')}> Layout & Display

Display the notification bell in the form

updateStyleSettings('showIcon', checked)} />
)} {/* Typography — Pro */} {isPro && ( toggleSection('typography')}> Typography
updateStyleSettings('fontFamily', v)} globalTokenId="body" featureDefault="" />
)} {/* Container Styling — Pro */} {isPro && ( toggleSection('containerStyling')}> Container Styling
updateStyleSettings('borderRadius', value)} min={0} max={20} step={1} /> updateStyleSettings('padding', value)} min={0} max={48} step={2} /> updateStyleSettings('margin', value)} min={0} max={48} step={2} /> updateStyleSettings('borderWidth', value)} min={0} max={4} step={1} /> updateStyleSettings('borderColor', v)} featureDefault="#e5e7eb" />
)} {/* Icon Styling — Pro */} {isPro && ( toggleSection('iconStyling')}> Icon Styling
updateStyleSettings('iconBackgroundColor', v)} featureDefault="#00226b" /> updateStyleSettings('iconColor', v)} featureDefault="#ffffff" />
updateStyleSettings('iconSize', value)} min={12} max={32} step={1} /> updateStyleSettings('iconBorderRadius', value)} min={0} max={50} step={5} unit="%" />
)} {/* Button Styling — Pro */} {isPro && ( toggleSection('buttonStyling')}> Button Styling
updateStyleSettings('primaryColor', v)} globalTokenId="primary" featureDefault="#00226b" /> updateStyleSettings('buttonTextColor', v)} featureDefault="#ffffff" /> updateStyleSettings('buttonBorderColor', v)} featureDefault="#00226b" fullWidth />
updateStyleSettings('buttonBorderWidth', value)} min={0} max={6} step={1} /> updateStyleSettings('buttonBorderRadius', value)} min={0} max={24} step={1} /> updateStyleSettings('buttonPadding', value)} min={4} max={24} step={2} />
)} {/* Input Field Styling — Pro */} {isPro && ( toggleSection('inputStyling')}> Input Field Styling
updateStyleSettings('inputBackgroundColor', v)} featureDefault="#ffffff" /> updateStyleSettings('inputTextColor', v)} featureDefault="#1f2937" /> updateStyleSettings('inputBorderColor', v)} featureDefault="#d1d5db" />
updateStyleSettings('inputBorderWidth', value)} min={0} max={6} step={1} /> updateStyleSettings('inputBorderRadius', value)} min={0} max={16} step={1} />
)} {/* Form Content — Pro */} {isPro && ( toggleSection('formContent')}> Form Content
updateFormSettings('formTitle', e.target.value)} placeholder="Get notified when available" />
updateFormSettings('emailPlaceholder', e.target.value)} placeholder="Enter your email address" />
updateFormSettings('buttonText', e.target.value)} placeholder="Notify Me" />