# FlexForm

A flexible grid-based form layout system that allows you to create responsive forms with automatic row wrapping and column spanning.

## Features

- **Grid-Based Layout**: 12-column grid system for flexible form layouts
- **Responsive Design**: Automatic wrapping and responsive behavior
- **Column Spanning**: Cells can span multiple columns (1-12)
- **Layout Modes**: Supports both vertical and horizontal field layouts
- **Form Field Integration**: Built-in FormField integration for labels and validation
- **Empty Cell Support**: Placeholder cells for layout alignment
- **Row Breaking**: Manual row breaks for precise layout control

## Installation

```bash
npm install @ticatec/uniface-element
```

## Usage

### Basic Usage

```svelte
<script>
  import FlexForm, { CellField } from '@ticatec/uniface-element/flex-form';
  import TextEditor from '@ticatec/uniface-element/text-editor';
  
  let formData = {};
</script>

<FlexForm>
  <CellField span={6} label="First Name" required>
    <TextEditor bind:value={formData.firstName} />
  </CellField>
  
  <CellField span={6} label="Last Name" required>
    <TextEditor bind:value={formData.lastName} />
  </CellField>
  
  <CellField span={12} label="Email Address">
    <TextEditor bind:value={formData.email} />
  </CellField>
</FlexForm>
```

### Complete Form Example

```svelte
<script>
  import FlexForm, { CellField, EmptyCell, RowBreak } from '@ticatec/uniface-element/flex-form';
  import TextEditor from '@ticatec/uniface-element/text-editor';
  import DatePicker from '@ticatec/uniface-element/date-picker';
  import OptionsSelect from '@ticatec/uniface-element/options-select';
  import MemoEditor from '@ticatec/uniface-element/memo-editor';
  
  let formData = {};
  let errors = {};
  
  const genderOptions = [
    { code: 'F', text: 'Female' },
    { code: 'M', text: 'Male' }
  ];
  
  const countries = [
    { code: 'AU', text: 'Australia' },
    { code: 'NZ', text: 'New Zealand' },
    { code: 'US', text: 'United States' }
  ];
</script>

<FlexForm style="max-width: 800px; margin: 0 auto;">
  <CellField span={4} label="Full Name" required error={errors.name}>
    <TextEditor 
      bind:value={formData.name} 
      variant="filled"
      placeholder="Enter full name"
    />
  </CellField>
  
  <CellField span={4} label="Date of Birth" required error={errors.dob}>
    <DatePicker 
      bind:value={formData.dob} 
      variant="filled"
      max={new Date()}
    />
  </CellField>
  
  <CellField span={4} label="Gender" required error={errors.gender}>
    <OptionsSelect 
      bind:value={formData.gender} 
      variant="filled"
      options={genderOptions}
    />
  </CellField>
  
  <CellField span={6} label="Nationality" error={errors.nationality}>
    <OptionsSelect 
      bind:value={formData.nationality} 
      variant="filled"
      options={countries}
    />
  </CellField>
  
  <EmptyCell span={6} />
  
  <CellField span={12} label="Additional Notes" error={errors.notes}>
    <MemoEditor 
      bind:value={formData.notes} 
      variant="filled"
      input$rows={4}
      input$maxLength={300}
      showIndicator
    />
  </CellField>
</FlexForm>
```

### Horizontal Layout

```svelte
<FlexForm fieldLayout="horizontal">
  <CellField span={6} label="Start Date">
    <DatePicker bind:value={startDate} variant="filled" />
  </CellField>
  
  <CellField span={6} label="End Date">
    <DatePicker bind:value={endDate} variant="filled" />
  </CellField>
</FlexForm>
```

## API Reference

### FlexForm

Main container component for the flexible form layout.

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `style` | `string` | `''` | Custom CSS styles for the form container |
| `fieldLayout` | `'vertical' \| 'horizontal'` | `'vertical'` | Layout mode for form fields |

#### Slots

| Slot | Description |
|------|-------------|
| default | Form content including CellField, EmptyCell, and RowBreak components |

### CellField

A form field component that spans specified columns in the grid.

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `span` | `number` | `1` | Number of columns to span (1-12) |
| `label` | `string` | `"Label:"` | Label text for the form field |
| `style` | `string` | `''` | Custom CSS styles for the field |
| `label$style` | `string` | `''` | Custom CSS styles for the label |
| `required` | `boolean` | `false` | Whether the field is required |
| `error` | `string \| null` | `null` | Error message to display |
| `labelSuffix` | `string` | `':'` | Text to append to the label |

#### Slots

| Slot | Description |
|------|-------------|
| default | Form control content (input, select, etc.) |

### EmptyCell

A placeholder cell for layout spacing and alignment.

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `span` | `number` | `1` | Number of columns to span (1-12) |

### RowBreak

Forces a new row in the form layout.

## Grid System

The FlexForm uses a 12-column grid system where each CellField can span 1-12 columns:

- **span={1}**: 8.33% width (1/12)
- **span={2}**: 16.67% width (2/12)
- **span={3}**: 25% width (3/12)
- **span={4}**: 33.33% width (4/12)
- **span={6}**: 50% width (6/12)
- **span={8}**: 66.67% width (8/12)
- **span={12}**: 100% width (12/12)

## Layout Examples

### Three Column Layout

```svelte
<FlexForm>
  <CellField span={4} label="Field 1">
    <TextEditor bind:value={field1} />
  </CellField>
  
  <CellField span={4} label="Field 2">
    <TextEditor bind:value={field2} />
  </CellField>
  
  <CellField span={4} label="Field 3">
    <TextEditor bind:value={field3} />
  </CellField>
</FlexForm>
```

### Mixed Width Layout

```svelte
<FlexForm>
  <CellField span={8} label="Primary Field">
    <TextEditor bind:value={primary} />
  </CellField>
  
  <CellField span={4} label="Secondary">
    <TextEditor bind:value={secondary} />
  </CellField>
  
  <CellField span={3} label="Small">
    <TextEditor bind:value={small1} />
  </CellField>
  
  <CellField span={3} label="Small">
    <TextEditor bind:value={small2} />
  </CellField>
  
  <CellField span={6} label="Medium">
    <TextEditor bind:value={medium} />
  </CellField>
</FlexForm>
```

### Layout with Empty Cells

```svelte
<FlexForm>
  <CellField span={4} label="Left Field">
    <TextEditor bind:value={left} />
  </CellField>
  
  <EmptyCell span={4} />
  
  <CellField span={4} label="Right Field">
    <TextEditor bind:value={right} />
  </CellField>
</FlexForm>
```

### Manual Row Breaks

```svelte
<FlexForm>
  <CellField span={6} label="Field 1">
    <TextEditor bind:value={field1} />
  </CellField>
  
  <CellField span={4} label="Field 2">
    <TextEditor bind:value={field2} />
  </CellField>
  
  <RowBreak />
  
  <CellField span={8} label="New Row Field">
    <TextEditor bind:value={field3} />
  </CellField>
</FlexForm>
```

## Responsive Design

The FlexForm automatically adapts to different screen sizes. You can enhance responsiveness with custom CSS:

```svelte
<FlexForm style="max-width: 1200px; margin: 0 auto;">
  <CellField span={6} label="Responsive Field">
    <TextEditor bind:value={value} />
  </CellField>
</FlexForm>

<style>
  @media (max-width: 768px) {
    :global(.flex-form .form-cell) {
      width: 100% !important;
    }
  }
</style>
```

## Validation and Error Handling

```svelte
<script>
  let formData = {
    name: '',
    email: '',
    phone: ''
  };
  
  let errors = {};
  
  function validateForm() {
    errors = {};
    
    if (!formData.name) {
      errors.name = 'Name is required';
    }
    
    if (!formData.email) {
      errors.email = 'Email is required';
    } else if (!/\S+@\S+\.\S+/.test(formData.email)) {
      errors.email = 'Please enter a valid email address';
    }
    
    if (!formData.phone) {
      errors.phone = 'Phone number is required';
    }
    
    return Object.keys(errors).length === 0;
  }
  
  function handleSubmit() {
    if (validateForm()) {
      console.log('Form submitted:', formData);
    }
  }
</script>

<FlexForm>
  <CellField span={12} label="Full Name" required error={errors.name}>
    <TextEditor 
      bind:value={formData.name}
      variant="filled"
      placeholder="Enter your full name"
    />
  </CellField>
  
  <CellField span={6} label="Email Address" required error={errors.email}>
    <TextEditor 
      bind:value={formData.email}
      variant="filled"
      placeholder="Enter email address"
    />
  </CellField>
  
  <CellField span={6} label="Phone Number" required error={errors.phone}>
    <TextEditor 
      bind:value={formData.phone}
      variant="filled"
      placeholder="Enter phone number"
    />
  </CellField>
  
  <CellField span={12}>
    <button type="button" on:click={handleSubmit}>
      Submit Form
    </button>
  </CellField>
</FlexForm>
```

## Styling

### Custom Form Styling

```svelte
<FlexForm 
  style="
    border: 1px solid #e1e5e9;
    border-radius: 8px;
    padding: 24px;
    background: #fafbfc;
  "
>
  <CellField 
    span={6} 
    label="Styled Field"
    label$style="color: #2563eb; font-weight: 600;"
  >
    <TextEditor bind:value={value} variant="filled" />
  </CellField>
</FlexForm>
```

### CSS Classes

```css
.custom-flex-form {
  max-width: 800px;
  margin: 2rem auto;
  padding: 2rem;
  border: 1px solid #e2e8f0;
  border-radius: 0.5rem;
  background: white;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.custom-flex-form .form-cell {
  margin-bottom: 1rem;
}
```

## Best Practices

### 1. Consistent Spanning

Use consistent column spans for similar field types:

```svelte
<FlexForm>
  <!-- Personal Information -->
  <CellField span={6} label="First Name" required>
    <TextEditor bind:value={firstName} />
  </CellField>
  
  <CellField span={6} label="Last Name" required>
    <TextEditor bind:value={lastName} />
  </CellField>
  
  <!-- Contact Information -->
  <CellField span={6} label="Email" required>
    <TextEditor bind:value={email} />
  </CellField>
  
  <CellField span={6} label="Phone">
    <TextEditor bind:value={phone} />
  </CellField>
</FlexForm>
```

### 2. Logical Grouping

Group related fields together and use full-width fields for important data:

```svelte
<FlexForm>
  <!-- Full-width for primary identifier -->
  <CellField span={12} label="Company Name" required>
    <TextEditor bind:value={companyName} />
  </CellField>
  
  <!-- Address fields in smaller columns -->
  <CellField span={8} label="Street Address">
    <TextEditor bind:value={address} />
  </CellField>
  
  <CellField span={4} label="Postal Code">
    <TextEditor bind:value={postalCode} />
  </CellField>
</FlexForm>
```

### 3. Responsive Considerations

Consider how your layout will appear on mobile devices:

```svelte
<FlexForm class="responsive-form">
  <CellField span={4} label="Field 1">
    <TextEditor bind:value={field1} />
  </CellField>
  
  <CellField span={4} label="Field 2">
    <TextEditor bind:value={field2} />
  </CellField>
  
  <CellField span={4} label="Field 3">
    <TextEditor bind:value={field3} />
  </CellField>
</FlexForm>

<style>
  @media (max-width: 768px) {
    :global(.responsive-form .form-cell) {
      width: 100% !important;
    }
  }
</style>
```

### 4. Error State Management

Maintain consistent error handling across all fields:

```svelte
<script>
  function validateField(field, value) {
    if (!value || value.trim() === '') {
      return `${field} is required`;
    }
    return null;
  }
  
  $: errors = {
    name: validateField('Name', formData.name),
    email: validateField('Email', formData.email)
  };
</script>
```

## Integration with Other Components

### With DatePicker

```svelte
<FlexForm>
  <CellField span={4} label="Start Date" required>
    <DatePicker 
      bind:value={startDate} 
      variant="filled"
      max={endDate}
    />
  </CellField>
  
  <CellField span={4} label="End Date" required>
    <DatePicker 
      bind:value={endDate} 
      variant="filled"
      min={startDate}
    />
  </CellField>
</FlexForm>
```

### With OptionsSelect

```svelte
<FlexForm>
  <CellField span={6} label="Country" required>
    <OptionsSelect 
      bind:value={country} 
      variant="filled"
      options={countryOptions}
      placeholder="Select a country"
    />
  </CellField>
  
  <CellField span={6} label="State/Province">
    <OptionsSelect 
      bind:value={state} 
      variant="filled"
      options={stateOptions}
      disabled={!country}
    />
  </CellField>
</FlexForm>
```

## Accessibility Features

- **Semantic Structure**: Proper form field labeling and association
- **Keyboard Navigation**: Standard form navigation patterns
- **Screen Reader Support**: Proper ARIA attributes and roles
- **Error Announcements**: Clear error message association
- **Focus Management**: Logical tab order through fields

## Browser Support

- **Modern Browsers**: Chrome, Firefox, Safari, Edge (latest versions)
- **Mobile Browsers**: iOS Safari, Chrome Mobile, Firefox Mobile
- **CSS Flexbox**: Required for layout functionality

## Related Components

- **FormField**: Base form field component
- **TextEditor**: Single-line text input
- **MemoEditor**: Multi-line text area
- **DatePicker**: Date selection component
- **OptionsSelect**: Dropdown selection component

## License

MIT License - see LICENSE file for details.