UNPKG

@vulform/react

Version:

React components for VulForm contact form management

565 lines (461 loc) 14.7 kB
# @vulform/react React components for VulForm contact form management. ## Installation ```bash npm install @vulform/react # or yarn add @vulform/react # or bun add @vulform/react ``` ## Quick Start ```jsx import { VulForm } from '@vulform/react'; function ContactPage() { return ( <VulForm templateId='your-template-id' apiKey='vf_your_api_key_here' onSuccess={response => console.log('Form submitted!', response)} onError={error => console.error('Submission failed:', error)} /> ); } ``` ## URL Configuration VulForm React supports flexible URL configuration for different deployment scenarios: ### 1. **Using VulForm SaaS (Default)** No configuration needed - automatically uses `https://api.vulform.dev`: ```jsx <VulForm templateId='your-template-id' apiKey='vf_your_api_key_here' // apiUrl is auto-detected /> ``` ### 2. **Self-Hosted VulForm** Use relative URLs for same-domain deployment: ```jsx <VulForm templateId='your-template-id' apiKey='vf_your_api_key_here' apiUrl='/api/v1' /> ``` ### 3. **Custom Domain** Point to your custom VulForm instance: ```jsx <VulForm templateId='your-template-id' apiKey='vf_your_api_key_here' apiUrl='https://forms.mycompany.com/api' /> ``` ### 4. **Environment Variables** Set up environment variables for automatic configuration: ```bash # Next.js NEXT_PUBLIC_VULFORM_API_KEY=vf_your_key_here NEXT_PUBLIC_VULFORM_BASE_URL=https://forms.mycompany.com/api # Create React App REACT_APP_VULFORM_API_KEY=vf_your_key_here REACT_APP_VULFORM_BASE_URL=https://forms.mycompany.com/api ``` Then use without props: ```jsx <VulForm templateId='your-template-id' // apiKey and apiUrl are read from environment variables /> ``` ### URL Resolution Priority VulForm resolves the API URL in this order: 1. **`apiUrl` prop** (highest priority) 2. **Environment variables**: `NEXT_PUBLIC_VULFORM_BASE_URL` or `REACT_APP_VULFORM_BASE_URL` 3. **Auto-detection**: - Development: `http://localhost:3000/api/v1` - Production: `https://api.vulform.dev` (SaaS) ## Props | Prop | Type | Default | Description | | -------------------- | -------------------------------------- | ----------------------------------------- | ----------------------------------------- | | `templateId` | `string` | **Required** | Your VulForm template ID | | `apiKey` | `string` | `process.env.NEXT_PUBLIC_VULFORM_API_KEY` | Your VulForm API key | | `apiUrl` | `string` | Auto-detected | VulForm API URL | | `theme` | `'auto' \| 'light' \| 'dark'` | `'auto'` | Form theme | | `className` | `string` | `''` | CSS class for the form container | | `style` | `React.CSSProperties` | `{}` | Inline styles for the form container | | `prefill` | `object` | `{}` | Pre-fill form fields | | `onSuccess` | `(response: any) => void` | `undefined` | Success callback | | `onError` | `(error: VulFormError) => void` | `undefined` | Error callback | | `onValidationError` | `(errors: ValidationErrors) => void` | `undefined` | Validation error callback | | `onFieldChange` | `(field: string, value: any) => void` | `undefined` | Field change callback | | `enableAnalytics` | `boolean` | `true` | Enable form analytics | | `spamProtection` | `boolean` | `true` | Enable spam protection | | `loadingState` | `'default' \| 'skeleton' \| 'spinner'` | `'default'` | Loading state style | | `resetOnSuccess` | `boolean` | `true` | Reset form after successful submission | | `showSuccessMessage` | `boolean` | `true` | Show success message after submission | | `autoRedirect` | `boolean` | `false` | Auto-redirect after successful submission | ## Advanced Usage ### Custom Styling ```jsx <VulForm templateId='your-template-id' className='my-custom-form' style={{ maxWidth: '600px', margin: '0 auto', padding: '2rem', backgroundColor: '#f9fafb', borderRadius: '0.5rem', }} /> ``` ### Form Events ```jsx <VulForm templateId='your-template-id' onSuccess={response => { console.log('Form submitted successfully:', response); // Redirect to thank you page window.location.href = '/thank-you'; }} onError={error => { console.error('Form submission failed:', error); // Show custom error message alert(`Error: ${error.message}`); }} onFieldChange={(fieldName, value) => { console.log(`Field ${fieldName} changed to:`, value); // Custom field validation or side effects }} /> ``` ### Pre-filling Fields ```jsx <VulForm templateId='your-template-id' prefill={{ name: 'John Doe', email: 'john@example.com', company: 'Acme Corp', }} /> ``` ### Using the Hook Directly For more control, use the `useVulForm` hook: ```jsx import { useVulForm } from '@vulform/react'; function CustomForm() { const { template, loading, error, submitting, submitted, formData, validationErrors, updateField, submitForm, resetForm, } = useVulForm({ templateId: 'your-template-id', apiKey: 'vf_your_api_key_here', apiUrl: 'https://forms.mycompany.com/api', // Optional onSuccess: response => console.log('Success!', response), onError: error => console.error('Error:', error), }); if (loading) return <div>Loading form...</div>; if (error) return <div>Error: {error.message}</div>; if (submitted) return <div>Thank you for your submission!</div>; return ( <form onSubmit={e => { e.preventDefault(); submitForm(); }} > {template?.fields.map(field => ( <div key={field.id}> <label>{field.label}</label> <input type={field.type} value={formData[field.name] || ''} onChange={e => updateField(field.name, e.target.value)} disabled={submitting} /> {validationErrors[field.name] && ( <span className='error'>{validationErrors[field.name]}</span> )} </div> ))} <button type='submit' disabled={submitting}> {submitting ? 'Submitting...' : 'Submit'} </button> </form> ); } ``` ## Deployment Examples ### Next.js App Router ```jsx // app/contact/page.tsx import { VulForm } from '@vulform/react'; export default function ContactPage() { return ( <div className='container mx-auto py-8'> <h1 className='text-3xl font-bold mb-8'>Contact Us</h1> <VulForm templateId={process.env.NEXT_PUBLIC_VULFORM_TEMPLATE_ID} // API key and URL are read from environment variables onSuccess={() => { // Handle success (e.g., show thank you message, redirect) }} /> </div> ); } ``` ### Create React App ```jsx // src/components/ContactForm.jsx import { VulForm } from '@vulform/react'; function ContactForm() { return ( <VulForm templateId={process.env.REACT_APP_VULFORM_TEMPLATE_ID} // Configuration is read from REACT_APP_* environment variables className='max-w-md mx-auto' onSuccess={response => { console.log('Form submitted:', response); }} /> ); } export default ContactForm; ``` ### Self-Hosted Setup ```jsx // For self-hosted VulForm instance <VulForm templateId='your-template-id' apiKey='vf_your_api_key_here' apiUrl='/api/v1' // Relative URL for same-domain deployment /> ``` ## TypeScript Support Full TypeScript support with comprehensive type definitions: ```tsx import { VulForm, VulFormProps, useVulForm } from '@vulform/react'; import type { SubmissionResponse, VulFormError, ValidationErrors } from '@vulform/core'; const formProps: VulFormProps = { templateId: 'your-template-id', apiKey: 'vf_your_key_here', onSuccess: (response: SubmissionResponse) => { console.log('Success:', response); }, onError: (error: VulFormError) => { console.error('Error:', error); }, onValidationError: (errors: ValidationErrors) => { console.log('Validation errors:', errors); }, }; export default function TypedForm() { return <VulForm {...formProps} />; } ``` ## Components ### VulForm The main component that renders a complete form based on a template. ```tsx <VulForm templateId='contact-form' apiKey='vf_abc123' // Optional if set in env apiUrl='/api/v1' // Optional, defaults to /api/v1 // Styling theme='auto' // 'auto' | 'light' | 'dark' | custom theme object className='my-form' // Data prefill={{ name: 'John Doe' }} // Event handlers onSuccess={response => console.log('Success!', response)} onError={error => console.error('Error:', error)} onValidationError={errors => console.log('Validation errors:', errors)} onFieldChange={(fieldName, value) => console.log('Field changed:', fieldName, value)} // Features enableAnalytics={true} spamProtection={true} resetOnSuccess={true} showSuccessMessage={true} /> ``` ### Individual Components ```tsx import { FormField, FormLoader, FormSuccess, FormErrorComponent } from '@vulform/react'; // Custom loading state <FormLoader loadingState="custom" /> // Success message <FormSuccess message="Thank you!" onReset={() => resetForm()} /> // Error display <FormErrorComponent error={{ code: 'NETWORK_ERROR', message: 'Connection failed' }} onRetry={() => retrySubmission()} /> ``` ## Hooks ### useVulForm Custom hook for building your own form components: ```tsx import { useVulForm } from '@vulform/react'; function CustomForm() { const { template, loading, error, submitting, formData, validationErrors, updateField, submitForm, resetForm, } = useVulForm({ templateId: 'contact-form', onSuccess: response => console.log('Success!'), onError: error => console.error('Error:', error), }); if (loading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <form onSubmit={e => { e.preventDefault(); submitForm(); }} > {template?.fields.map(field => ( <input key={field.id} type={field.type} value={formData[field.name] || ''} onChange={e => updateField(field.name, e.target.value)} /> ))} <button type='submit' disabled={submitting}> {submitting ? 'Sending...' : 'Submit'} </button> </form> ); } ``` ### useFieldValidation Real-time field validation: ```tsx import { useFieldValidation } from '@vulform/react'; function EmailField({ field, apiClient }) { const [value, setValue] = useState(''); const { error, isValidating } = useFieldValidation({ field, value, apiClient, debounceMs: 300, }); return ( <div> <input value={value} onChange={e => setValue(e.target.value)} style={{ borderColor: error ? 'red' : undefined }} /> {isValidating && <span>Validating...</span>} {error && <span style={{ color: 'red' }}>{error}</span>} </div> ); } ``` ## Styling ### CSS Variables VulForm components use CSS variables that you can customize: ```css .vulform-container { --vulform-primary: #3b82f6; --vulform-secondary: #1e40af; --vulform-background: #ffffff; --vulform-text: #374151; --vulform-border: #d1d5db; --vulform-border-radius: 0.5rem; --vulform-font-family: 'Inter', sans-serif; --vulform-font-size: 1rem; --vulform-spacing: 1rem; } ``` ### Custom Themes ```tsx const customTheme = { primaryColor: '#10b981', secondaryColor: '#059669', backgroundColor: '#f9fafb', textColor: '#111827', borderColor: '#d1d5db', borderRadius: '0.75rem', fontFamily: 'system-ui', fontSize: '1rem', spacing: '1.5rem', }; <VulForm templateId='contact-form' theme={customTheme} />; ``` ### Tailwind CSS VulForm works great with Tailwind CSS. Components include sensible default classes: ```tsx <VulForm templateId='contact-form' className='max-w-2xl mx-auto p-6 bg-white rounded-lg shadow-lg' /> ``` ## Form Templates Create form templates in the VulForm dashboard, then reference them by ID: ```tsx // Template ID from dashboard <VulForm templateId='cmc2o5rpm0007ju0d4et2g97d' /> ``` Templates include: - Field definitions (text, email, textarea, select, etc.) - Validation rules - Layout settings (vertical, horizontal, grid) - Styling and themes - Success/error messages ## Error Handling ```tsx import { VulFormError } from '@vulform/react'; <VulForm templateId='contact-form' onError={(error: VulFormError) => { switch (error.code) { case 'MISSING_API_KEY': console.error('API key not configured'); break; case 'TEMPLATE_NOT_FOUND': console.error('Form template not found'); break; case 'RATE_LIMIT_EXCEEDED': console.error('Too many requests'); break; case 'NETWORK_ERROR': console.error('Network connection failed'); break; default: console.error('Unknown error:', error.message); } }} />; ``` ## 📦 CDN Usage **Via unpkg.com:** ```html <script src="https://unpkg.com/@vulform/react@latest/dist/index.js"></script> ``` **Via jsDelivr:** ```html <script src="https://cdn.jsdelivr.net/npm/@vulform/react@latest/dist/index.js"></script> ``` > **Note:** For React applications, we recommend using the npm package for better tree-shaking and TypeScript support. ## License MIT