# FlexForm 弹性表单布局

基于网格的弹性表单布局系统，允许您创建具有自动换行和列跨越功能的响应式表单。

## 特性

- **网格布局系统**: 12列网格系统，实现灵活的表单布局
- **响应式设计**: 自动换行和响应式行为
- **列跨越**: 单元格可跨越多列（1-12列）
- **布局模式**: 支持垂直和水平字段布局
- **表单字段集成**: 内置FormField集成，支持标签和验证
- **空单元格支持**: 用于布局对齐的占位单元格
- **手动换行**: 精确布局控制的手动换行

## 安装

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

## 使用方法

### 基本用法

```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="名" required>
    <TextEditor bind:value={formData.firstName} />
  </CellField>
  
  <CellField span={6} label="姓" required>
    <TextEditor bind:value={formData.lastName} />
  </CellField>
  
  <CellField span={12} label="邮箱地址">
    <TextEditor bind:value={formData.email} />
  </CellField>
</FlexForm>
```

### 完整表单示例

```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: '女' },
    { code: 'M', text: '男' }
  ];
  
  const countries = [
    { code: 'AU', text: '澳大利亚' },
    { code: 'NZ', text: '新西兰' },
    { code: 'US', text: '美国' }
  ];
</script>

<FlexForm style="max-width: 800px; margin: 0 auto;">
  <CellField span={4} label="姓名" required error={errors.name}>
    <TextEditor 
      bind:value={formData.name} 
      variant="filled"
      placeholder="请输入姓名"
    />
  </CellField>
  
  <CellField span={4} label="出生日期" required error={errors.dob}>
    <DatePicker 
      bind:value={formData.dob} 
      variant="filled"
      max={new Date()}
    />
  </CellField>
  
  <CellField span={4} label="性别" required error={errors.gender}>
    <OptionsSelect 
      bind:value={formData.gender} 
      variant="filled"
      options={genderOptions}
    />
  </CellField>
  
  <CellField span={6} label="国籍" error={errors.nationality}>
    <OptionsSelect 
      bind:value={formData.nationality} 
      variant="filled"
      options={countries}
    />
  </CellField>
  
  <EmptyCell span={6} />
  
  <CellField span={12} label="备注" error={errors.notes}>
    <MemoEditor 
      bind:value={formData.notes} 
      variant="filled"
      input$rows={4}
      input$maxLength={300}
      showIndicator
    />
  </CellField>
</FlexForm>
```

### 水平布局

```svelte
<FlexForm fieldLayout="horizontal">
  <CellField span={6} label="开始日期">
    <DatePicker bind:value={startDate} variant="filled" />
  </CellField>
  
  <CellField span={6} label="结束日期">
    <DatePicker bind:value={endDate} variant="filled" />
  </CellField>
</FlexForm>
```

## API 参考

### FlexForm

弹性表单布局的主容器组件。

#### 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `style` | `string` | `''` | 表单容器的自定义CSS样式 |
| `fieldLayout` | `'vertical' \| 'horizontal'` | `'vertical'` | 表单字段的布局模式 |

#### 插槽

| 插槽 | 描述 |
|------|-------------|
| default | 表单内容，包括CellField、EmptyCell和RowBreak组件 |

### CellField

在网格中跨越指定列数的表单字段组件。

#### 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `span` | `number` | `1` | 跨越的列数（1-12） |
| `label` | `string` | `"Label:"` | 表单字段的标签文本 |
| `style` | `string` | `''` | 字段的自定义CSS样式 |
| `label$style` | `string` | `''` | 标签的自定义CSS样式 |
| `required` | `boolean` | `false` | 字段是否必填 |
| `error` | `string \| null` | `null` | 要显示的错误消息 |
| `labelSuffix` | `string` | `':'` | 附加到标签的文本 |

#### 插槽

| 插槽 | 描述 |
|------|-------------|
| default | 表单控件内容（输入框、选择器等） |

### EmptyCell

用于布局间隔和对齐的占位单元格。

#### 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `span` | `number` | `1` | 跨越的列数（1-12） |

### RowBreak

强制在表单布局中开始新行。

## 网格系统

FlexForm使用12列网格系统，每个CellField可以跨越1-12列：

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

## 布局示例

### 三列布局

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

### 混合宽度布局

```svelte
<FlexForm>
  <CellField span={8} label="主要字段">
    <TextEditor bind:value={primary} />
  </CellField>
  
  <CellField span={4} label="次要字段">
    <TextEditor bind:value={secondary} />
  </CellField>
  
  <CellField span={3} label="小字段">
    <TextEditor bind:value={small1} />
  </CellField>
  
  <CellField span={3} label="小字段">
    <TextEditor bind:value={small2} />
  </CellField>
  
  <CellField span={6} label="中等字段">
    <TextEditor bind:value={medium} />
  </CellField>
</FlexForm>
```

### 带空单元格的布局

```svelte
<FlexForm>
  <CellField span={4} label="左侧字段">
    <TextEditor bind:value={left} />
  </CellField>
  
  <EmptyCell span={4} />
  
  <CellField span={4} label="右侧字段">
    <TextEditor bind:value={right} />
  </CellField>
</FlexForm>
```

### 手动换行

```svelte
<FlexForm>
  <CellField span={6} label="字段1">
    <TextEditor bind:value={field1} />
  </CellField>
  
  <CellField span={4} label="字段2">
    <TextEditor bind:value={field2} />
  </CellField>
  
  <RowBreak />
  
  <CellField span={8} label="新行字段">
    <TextEditor bind:value={field3} />
  </CellField>
</FlexForm>
```

## 响应式设计

FlexForm自动适应不同的屏幕尺寸。您可以使用自定义CSS增强响应性：

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

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

## 验证和错误处理

```svelte
<script>
  let formData = {
    name: '',
    email: '',
    phone: ''
  };
  
  let errors = {};
  
  function validateForm() {
    errors = {};
    
    if (!formData.name) {
      errors.name = '姓名为必填项';
    }
    
    if (!formData.email) {
      errors.email = '邮箱为必填项';
    } else if (!/\S+@\S+\.\S+/.test(formData.email)) {
      errors.email = '请输入有效的邮箱地址';
    }
    
    if (!formData.phone) {
      errors.phone = '电话号码为必填项';
    }
    
    return Object.keys(errors).length === 0;
  }
  
  function handleSubmit() {
    if (validateForm()) {
      console.log('表单提交:', formData);
    }
  }
</script>

<FlexForm>
  <CellField span={12} label="姓名" required error={errors.name}>
    <TextEditor 
      bind:value={formData.name}
      variant="filled"
      placeholder="请输入您的姓名"
    />
  </CellField>
  
  <CellField span={6} label="邮箱地址" required error={errors.email}>
    <TextEditor 
      bind:value={formData.email}
      variant="filled"
      placeholder="请输入邮箱地址"
    />
  </CellField>
  
  <CellField span={6} label="电话号码" required error={errors.phone}>
    <TextEditor 
      bind:value={formData.phone}
      variant="filled"
      placeholder="请输入电话号码"
    />
  </CellField>
  
  <CellField span={12}>
    <button type="button" on:click={handleSubmit}>
      提交表单
    </button>
  </CellField>
</FlexForm>
```

## 样式

### 自定义表单样式

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

### CSS 类

```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;
}
```

## 最佳实践

### 1. 一致的跨度设置

对相似类型的字段使用一致的列跨度：

```svelte
<FlexForm>
  <!-- 个人信息 -->
  <CellField span={6} label="名" required>
    <TextEditor bind:value={firstName} />
  </CellField>
  
  <CellField span={6} label="姓" required>
    <TextEditor bind:value={lastName} />
  </CellField>
  
  <!-- 联系信息 -->
  <CellField span={6} label="邮箱" required>
    <TextEditor bind:value={email} />
  </CellField>
  
  <CellField span={6} label="电话">
    <TextEditor bind:value={phone} />
  </CellField>
</FlexForm>
```

### 2. 逻辑分组

将相关字段分组，对重要数据使用全宽字段：

```svelte
<FlexForm>
  <!-- 主要标识符使用全宽 -->
  <CellField span={12} label="公司名称" required>
    <TextEditor bind:value={companyName} />
  </CellField>
  
  <!-- 地址字段使用较小列 -->
  <CellField span={8} label="街道地址">
    <TextEditor bind:value={address} />
  </CellField>
  
  <CellField span={4} label="邮政编码">
    <TextEditor bind:value={postalCode} />
  </CellField>
</FlexForm>
```

### 3. 响应式考虑

考虑您的布局在移动设备上的显示效果：

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

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

### 4. 错误状态管理

在所有字段中保持一致的错误处理：

```svelte
<script>
  function validateField(field, value) {
    if (!value || value.trim() === '') {
      return `${field}为必填项`;
    }
    return null;
  }
  
  $: errors = {
    name: validateField('姓名', formData.name),
    email: validateField('邮箱', formData.email)
  };
</script>
```

## 与其他组件集成

### 与DatePicker集成

```svelte
<FlexForm>
  <CellField span={4} label="开始日期" required>
    <DatePicker 
      bind:value={startDate} 
      variant="filled"
      max={endDate}
    />
  </CellField>
  
  <CellField span={4} label="结束日期" required>
    <DatePicker 
      bind:value={endDate} 
      variant="filled"
      min={startDate}
    />
  </CellField>
</FlexForm>
```

### 与OptionsSelect集成

```svelte
<FlexForm>
  <CellField span={6} label="国家" required>
    <OptionsSelect 
      bind:value={country} 
      variant="filled"
      options={countryOptions}
      placeholder="请选择国家"
    />
  </CellField>
  
  <CellField span={6} label="省/州">
    <OptionsSelect 
      bind:value={state} 
      variant="filled"
      options={stateOptions}
      disabled={!country}
    />
  </CellField>
</FlexForm>
```

## 无障碍功能

- **语义结构**: 正确的表单字段标签和关联
- **键盘导航**: 标准表单导航模式
- **屏幕阅读器支持**: 适当的ARIA属性和角色
- **错误通知**: 清晰的错误消息关联
- **焦点管理**: 通过字段的逻辑tab顺序

## 浏览器支持

- **现代浏览器**: Chrome、Firefox、Safari、Edge（最新版本）
- **移动浏览器**: iOS Safari、Chrome Mobile、Firefox Mobile
- **CSS Flexbox**: 布局功能必需

## 相关组件

- **FormField**: 基础表单字段组件
- **TextEditor**: 单行文本输入
- **MemoEditor**: 多行文本区域
- **DatePicker**: 日期选择组件
- **OptionsSelect**: 下拉选择组件

## 许可证

MIT许可证 - 详情请参阅LICENSE文件。