import React, { CSSProperties } from 'react'; import { useNode, UserComponent } from '@craftjs/core'; import { cssPropsToString } from '../../utils/style-helpers'; import { relayFormWiring } from '../../utils/form-relay-wiring'; import { escapeHtml, escapeAttr } from '../../utils/escape'; interface ContactFormField { type: 'text' | 'email' | 'tel' | 'textarea' | 'select'; label: string; name: string; placeholder: string; required: boolean; options?: string[]; } interface ContactFormProps { fields?: ContactFormField[]; submitText?: string; submitColor?: string; formAction?: string; successMessage?: string; style?: CSSProperties; labelColor?: string; inputBg?: string; inputBorder?: string; recipientEmail?: string; thankYouUrl?: string; } const defaultFields: ContactFormField[] = [ { type: 'text', label: 'Name', name: 'name', placeholder: 'Your name', required: true }, { type: 'email', label: 'Email', name: 'email', placeholder: 'your@email.com', required: true }, { type: 'tel', label: 'Phone', name: 'phone', placeholder: '(555) 123-4567', required: false }, { type: 'textarea', label: 'Message', name: 'message', placeholder: 'How can we help you?', required: true }, ]; export const ContactForm: UserComponent = ({ fields = defaultFields, submitText = 'Send Message', submitColor = '#3b82f6', formAction = '#', successMessage = 'Thank you! We\'ll get back to you soon.', style = {}, labelColor = '#374151', inputBg = '#ffffff', inputBorder = '#d1d5db', }) => { const { connectors: { connect, drag }, selected, } = useNode((node) => ({ selected: node.events.selected, })); const inputBaseStyle: CSSProperties = { width: '100%', padding: '10px 14px', fontSize: '14px', fontFamily: 'Inter, sans-serif', border: `1px solid ${inputBorder}`, borderRadius: '6px', backgroundColor: inputBg, color: '#1f2937', boxSizing: 'border-box', outline: 'none', }; return (
{ if (ref) connect(drag(ref)); }} action={formAction} method="POST" onSubmit={(e) => e.preventDefault()} style={{ padding: '32px', display: 'flex', flexDirection: 'column', gap: '20px', outline: selected ? '2px solid #3b82f6' : 'none', ...style, }} > {fields.map((field, i) => (
{field.type === 'textarea' ? ( `; } else if (field.type === 'select') { const opts = (field.options || []).map((o) => ``).join(''); inputHtml = ``; } else { inputHtml = ``; } return `
${labelHtml}${inputHtml}
`; }).join('\n '); const btnStyle = cssPropsToString({ padding: '12px 32px', fontSize: '16px', fontWeight: '600', fontFamily: 'Inter, sans-serif', color: '#ffffff', backgroundColor: props.submitColor || '#3b82f6', border: 'none', borderRadius: '8px', cursor: 'pointer', alignSelf: 'flex-start', }); const { marker, actionAttr, honeypot } = relayFormWiring(props.recipientEmail, props.thankYouUrl, props.formAction); return { html: `${marker} ${honeypot ? ` ${honeypot}\n` : ''}${fieldsHtml ? ` ${fieldsHtml}\n` : ''} `, }; };