# Form

## Description

A comprehensive form management component that provides state management, validation, error handling, and submission workflows. Built with TypeScript for type safety and supports both controlled and uncontrolled form patterns with extensive validation capabilities.

## Aliases

- Form
- FormProvider
- FormContainer
- FormWrapper

## Props Breakdown

**Extends:** `FormHTMLAttributes<HTMLFormElement>` (excluding `onSubmit`)

| Prop | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| `formRef` | `Ref<HTMLFormElement>` | - | No | Reference to the form element |
| `children` | `ReactNode` | - | No | Form fields and content |
| `formState` | `FormState` | - | No | Initial form state values |
| `onFormStateChange` | `FormStateChangeHandler` | - | No | Callback when form state changes |
| `formValidator` | `FormValidator` | - | No | Function to validate entire form |
| `onSubmit` | `FormSubmitHandler` | - | No | Form submission handler |
| `validateOnChange` | `boolean` | - | No | Whether to validate on field changes |
| `autosave` | `boolean` | `false` | No | Enable automatic form submission on value changes |
| `autosaveDelayMs` | `number` | - | No | Delay in milliseconds before autosave triggers |

Plus all standard HTML form attributes (method, action, encType, target, etc.) except `onSubmit`.

## Examples

### Basic Form
```tsx
import { Form, FormField, Input, Button } from '@delightui/components';

function BasicFormExample() {
  const handleSubmit = (values, setError) => {
    console.log('Form submitted:', values);
    
    // Example validation
    if (!values.email || !values.email.includes('@')) {
      setError('email', 'Please enter a valid email address');
      return;
    }
    
    // Process form submission
    alert('Form submitted successfully!');
  };

  return (
    <Form onSubmit={handleSubmit}>
      <FormField name="name" label="Full Name" required>
        <Input placeholder="Enter your name" />
      </FormField>
      
      <FormField name="email" label="Email Address" required>
        <Input inputType="Email" placeholder="Enter your email" />
      </FormField>
      
      <FormField name="message" label="Message">
        <TextArea placeholder="Your message..." rows={4} />
      </FormField>
      
      <Button actionType="submit">Submit Form</Button>
    </Form>
  );
}
```

### Form with Validation
```tsx
function ValidationFormExample() {
  const handleSubmit = (values, setError) => {
    // Custom validation logic
    let hasErrors = false;
    
    if (!values.password || values.password.length < 8) {
      setError('password', 'Password must be at least 8 characters');
      hasErrors = true;
    }
    
    if (values.password !== values.confirmPassword) {
      setError('confirmPassword', 'Passwords do not match');
      hasErrors = true;
    }
    
    if (!hasErrors) {
      console.log('Creating account:', values);
    }
  };

  const formValidator = (values, setError) => {
    let isValid = true;
    
    // Username validation
    if (!values.username || values.username.length < 3) {
      setError('username', 'Username must be at least 3 characters');
      isValid = false;
    }
    
    // Email validation
    if (!values.email || !/\S+@\S+\.\S+/.test(values.email)) {
      setError('email', 'Please enter a valid email');
      isValid = false;
    }
    
    return isValid;
  };

  return (
    <Form 
      onSubmit={handleSubmit}
      formValidator={formValidator}
      validateOnChange={true}
    >
      <FormField name="username" label="Username" required>
        <Input placeholder="Choose a username" />
      </FormField>
      
      <FormField name="email" label="Email" required>
        <Input inputType="Email" placeholder="your@email.com" />
      </FormField>
      
      <FormField name="password" label="Password" required>
        <Input inputType="Password" placeholder="Create password" />
      </FormField>
      
      <FormField name="confirmPassword" label="Confirm Password" required>
        <Input inputType="Password" placeholder="Confirm password" />
      </FormField>
      
      <div className="form-actions">
        <Button actionType="submit">Create Account</Button>
        <Button type="Outlined" actionType="reset">Clear Form</Button>
      </div>
    </Form>
  );
}
```

### Form with Initial State
```tsx
function InitialStateFormExample() {
  const initialFormState = {
    firstName: 'John',
    lastName: 'Doe',
    email: 'john.doe@example.com',
    role: 'developer',
    notifications: true
  };

  const handleSubmit = (values, setError) => {
    console.log('Updated profile:', values);
  };

  const handleStateChange = (state, setError) => {
    // Validate on state change
    if (state.email && !state.email.includes('@')) {
      setError('email', 'Invalid email format');
    }
  };

  return (
    <Form 
      formState={initialFormState}
      onSubmit={handleSubmit}
      onFormStateChange={handleStateChange}
    >
      <FormField name="firstName" label="First Name" required>
        <Input />
      </FormField>
      
      <FormField name="lastName" label="Last Name" required>
        <Input />
      </FormField>
      
      <FormField name="email" label="Email" required>
        <Input inputType="Email" />
      </FormField>
      
      <FormField name="role" label="Role">
        <Select>
          <Option value="developer">Developer</Option>
          <Option value="designer">Designer</Option>
          <Option value="manager">Manager</Option>
        </Select>
      </FormField>
      
      <FormField name="notifications" label="Email Notifications">
        <Checkbox>Send me email notifications</Checkbox>
      </FormField>
      
      <Button actionType="submit">Update Profile</Button>
    </Form>
  );
}
```

### Multi-Step Form
```tsx
function MultiStepFormExample() {
  const [currentStep, setCurrentStep] = useState(1);
  const [formData, setFormData] = useState({});

  const handleStepSubmit = (values, setError) => {
    setFormData(prev => ({ ...prev, ...values }));
    
    if (currentStep < 3) {
      setCurrentStep(prev => prev + 1);
    } else {
      // Final submission
      console.log('Complete form data:', { ...formData, ...values });
      alert('Form completed successfully!');
    }
  };

  return (
    <div className="multi-step-form">
      <div className="step-indicator">
        <Text>Step {currentStep} of 3</Text>
      </div>
      
      {currentStep === 1 && (
        <Form onSubmit={handleStepSubmit}>
          <Text type="Heading4">Personal Information</Text>
          
          <FormField name="firstName" label="First Name" required>
            <Input />
          </FormField>
          
          <FormField name="lastName" label="Last Name" required>
            <Input />
          </FormField>
          
          <FormField name="birthDate" label="Date of Birth">
            <DatePicker />
          </FormField>
          
          <Button actionType="submit">Next Step</Button>
        </Form>
      )}
      
      {currentStep === 2 && (
        <Form onSubmit={handleStepSubmit}>
          <Text type="Heading4">Contact Information</Text>
          
          <FormField name="email" label="Email" required>
            <Input inputType="Email" />
          </FormField>
          
          <FormField name="phone" label="Phone Number">
            <Input inputType="Tel" />
          </FormField>
          
          <FormField name="address" label="Address">
            <TextArea rows={3} />
          </FormField>
          
          <div className="step-actions">
            <Button 
              type="Outlined" 
              onClick={() => setCurrentStep(1)}
            >
              Previous
            </Button>
            <Button actionType="submit">Next Step</Button>
          </div>
        </Form>
      )}
      
      {currentStep === 3 && (
        <Form onSubmit={handleStepSubmit}>
          <Text type="Heading4">Preferences</Text>
          
          <FormField name="newsletter" label="Newsletter">
            <Checkbox>Subscribe to our newsletter</Checkbox>
          </FormField>
          
          <FormField name="theme" label="Preferred Theme">
            <RadioGroup>
              <RadioButton value="light">Light Theme</RadioButton>
              <RadioButton value="dark">Dark Theme</RadioButton>
              <RadioButton value="auto">Auto (System)</RadioButton>
            </RadioGroup>
          </FormField>
          
          <div className="step-actions">
            <Button 
              type="Outlined" 
              onClick={() => setCurrentStep(2)}
            >
              Previous
            </Button>
            <Button actionType="submit">Complete</Button>
          </div>
        </Form>
      )}
    </div>
  );
}
```

### Dynamic Form Fields
```tsx
function DynamicFormExample() {
  const [fieldCount, setFieldCount] = useState(1);

  const handleSubmit = (values, setError) => {
    const skills = [];
    for (let i = 1; i <= fieldCount; i++) {
      if (values[`skill${i}`]) {
        skills.push(values[`skill${i}`]);
      }
    }
    
    console.log('Skills:', skills);
  };

  const addField = () => setFieldCount(prev => prev + 1);
  const removeField = () => setFieldCount(prev => Math.max(1, prev - 1));

  return (
    <Form onSubmit={handleSubmit}>
      <Text type="Heading4">Skills</Text>
      
      {Array.from({ length: fieldCount }, (_, index) => (
        <FormField 
          key={index + 1}
          name={`skill${index + 1}`} 
          label={`Skill ${index + 1}`}
          required={index === 0}
        >
          <Input placeholder="Enter a skill" />
        </FormField>
      ))}
      
      <div className="dynamic-field-controls">
        <Button 
          type="Ghost" 
          onClick={addField}
          leadingIcon={<Icon icon="Add" />}
        >
          Add Skill
        </Button>
        
        {fieldCount > 1 && (
          <Button 
            type="Ghost" 
            onClick={removeField}
            leadingIcon={<Icon icon="Remove" />}
          >
            Remove Skill
          </Button>
        )}
      </div>
      
      <Button actionType="submit">Save Skills</Button>
    </Form>
  );
}
```

### File Upload Form
```tsx
function FileUploadFormExample() {
  const handleSubmit = (values, setError) => {
    if (!values.file) {
      setError('file', 'Please select a file to upload');
      return;
    }
    
    console.log('Uploading file:', values.file);
  };

  return (
    <Form onSubmit={handleSubmit}>
      <FormField name="title" label="Document Title" required>
        <Input placeholder="Enter document title" />
      </FormField>
      
      <FormField name="description" label="Description">
        <TextArea placeholder="Document description..." rows={3} />
      </FormField>
      
      <FormField name="category" label="Category" required>
        <Select>
          <Option value="report">Report</Option>
          <Option value="presentation">Presentation</Option>
          <Option value="document">Document</Option>
        </Select>
      </FormField>
      
      <FormField name="file" label="File" required>
        <Dropzone 
          accept=".pdf,.doc,.docx,.ppt,.pptx"
          maxSize={10485760} // 10MB
        >
          <Text>Drag and drop a file here, or click to select</Text>
          <Text type="BodySmall">Supports PDF, DOC, DOCX, PPT, PPTX (max 10MB)</Text>
        </Dropzone>
      </FormField>
      
      <FormField name="public" label="Visibility">
        <Checkbox>Make this document public</Checkbox>
      </FormField>
      
      <Button actionType="submit">Upload Document</Button>
    </Form>
  );
}
```

### Form with Custom Validation
```tsx
function CustomValidationExample() {
  const validatePassword = (setError, value) => {
    if (!value) {
      setError('Password is required');
      return false;
    }
    
    if (value.length < 8) {
      setError('Password must be at least 8 characters');
      return false;
    }
    
    if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
      setError('Password must contain uppercase, lowercase, and numbers');
      return false;
    }
    
    return true;
  };

  const handleSubmit = (values, setError) => {
    // Additional cross-field validation
    if (values.password !== values.confirmPassword) {
      setError('confirmPassword', 'Passwords do not match');
      return;
    }
    
    console.log('Account created:', values);
  };

  return (
    <Form onSubmit={handleSubmit}>
      <FormField name="email" label="Email" required>
        <Input inputType="Email" />
      </FormField>
      
      <FormField 
        name="password" 
        label="Password" 
        required
        validate={validatePassword}
      >
        <Input inputType="Password" />
      </FormField>
      
      <FormField name="confirmPassword" label="Confirm Password" required>
        <Input inputType="Password" />
      </FormField>
      
      <FormField name="terms" label="Agreement" required>
        <Checkbox>I agree to the terms and conditions</Checkbox>
      </FormField>
      
      <Button actionType="submit">Create Account</Button>
    </Form>
  );
}
```

### Async Form Submission
```tsx
function AsyncFormExample() {
  const [isSubmitting, setIsSubmitting] = useState(false);

  const handleSubmit = async (values, setError) => {
    setIsSubmitting(true);
    
    try {
      // Simulate API call
      const response = await fetch('/api/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(values)
      });
      
      if (!response.ok) {
        throw new Error('Submission failed');
      }
      
      const result = await response.json();
      console.log('Success:', result);
      alert('Message sent successfully!');
      
    } catch (error) {
      setError('general', 'Failed to send message. Please try again.');
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <Form onSubmit={handleSubmit}>
      <FormField name="name" label="Name" required>
        <Input disabled={isSubmitting} />
      </FormField>
      
      <FormField name="email" label="Email" required>
        <Input inputType="Email" disabled={isSubmitting} />
      </FormField>
      
      <FormField name="subject" label="Subject" required>
        <Input disabled={isSubmitting} />
      </FormField>
      
      <FormField name="message" label="Message" required>
        <TextArea rows={5} disabled={isSubmitting} />
      </FormField>
      
      <Button 
        actionType="submit" 
        loading={isSubmitting}
        disabled={isSubmitting}
      >
        Send Message
      </Button>
    </Form>
  );
}
```

### Autosave Form
```tsx
function AutosaveFormExample() {
  const [saveCount, setSaveCount] = useState(0);
  const [lastSaved, setLastSaved] = useState(null);

  const handleSubmit = async (values, setError) => {
    try {
      // Simulate API call to save draft
      const response = await fetch('/api/drafts', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(values)
      });
      
      if (response.ok) {
        setSaveCount(prev => prev + 1);
        setLastSaved(new Date().toLocaleTimeString());
        console.log('Draft auto-saved:', values);
      }
    } catch (error) {
      console.error('Failed to save draft:', error);
    }
  };

  return (
    <div>
      <Form 
        onSubmit={handleSubmit}
        autosave={true}
        autosaveDelayMs={2000} // Wait 2 seconds after user stops typing
      >
        <FormField name="title" label="Title">
          <Input placeholder="Enter title" />
        </FormField>
        
        <FormField name="content" label="Content">
          <TextArea 
            placeholder="Start writing..." 
            rows={10} 
          />
        </FormField>
        
        <FormField name="tags" label="Tags">
          <ChipInput 
            placeholder="Add tags" 
            options={['react', 'typescript', 'design', 'tutorial']}
          />
        </FormField>
        
        {lastSaved && (
          <Text type="BodySmall">
            Auto-saved {saveCount} times. Last saved at {lastSaved}
          </Text>
        )}
      </Form>
    </div>
  );
}
```

### Autosave with Manual Submit
```tsx
function AutosaveWithManualSubmitExample() {
  const [isDraft, setIsDraft] = useState(true);

  const handleAutosave = (values, setError) => {
    if (isDraft) {
      console.log('Draft auto-saved:', values);
      // Save to local storage or draft API
      localStorage.setItem('formDraft', JSON.stringify(values));
    }
  };

  const handlePublish = () => {
    setIsDraft(false);
    // Form will now submit normally
  };

  return (
    <Form 
      onSubmit={handleAutosave}
      autosave={isDraft}
      autosaveDelayMs={1000}
      formState={{
        title: localStorage.getItem('formDraft')?.title || '',
        content: localStorage.getItem('formDraft')?.content || ''
      }}
    >
      <FormField name="title" label="Article Title" required>
        <Input placeholder="Enter title" />
      </FormField>
      
      <FormField name="content" label="Article Content" required>
        <TextArea placeholder="Write your article..." rows={15} />
      </FormField>
      
      <FormField name="category" label="Category">
        <Select>
          <Option value="tech">Technology</Option>
          <Option value="design">Design</Option>
          <Option value="business">Business</Option>
        </Select>
      </FormField>
      
      <div className="form-actions">
        <Button type="Outlined">Save as Draft</Button>
        <Button 
          actionType="submit" 
          onClick={handlePublish}
        >
          Publish Article
        </Button>
      </div>
      
      {isDraft && (
        <Text type="BodySmall" style={{ marginTop: '8px' }}>
          Your changes are automatically saved as you type
        </Text>
      )}
    </Form>
  );
}
```