# CheckBox 复选框组件

一个功能丰富的复选框组件，支持多种状态包括半选状态，具备全面的事件处理和无障碍访问功能。非常适合单项选择、开关选项和表单控件。

## 功能特性

- **多种状态**: 选中、未选中和半选状态
- **事件处理**: 支持点击、值变化、聚焦和失焦事件
- **无障碍访问**: 正确的ARIA属性和键盘导航
- **自动聚焦**: 可选的自动聚焦功能
- **自定义样式**: 灵活的样式定制和紧凑模式
- **只读和禁用**: 支持非交互状态
- **程序化控制**: 聚焦管理和值控制

## 基本用法

```svelte
<script>
import CheckBox from '@ticatec/uniface-element/CheckBox';

let isChecked = false;

const handleChange = (value) => {
  console.log('复选框状态变化:', value);
  isChecked = value;
};
</script>

<CheckBox 
  label="接受条款和条件"
  bind:value={isChecked}
  onChange={handleChange}
/>
```

## 属性参数

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `label` | `string \| null` | `null` | 复选框旁边显示的文本标签 |
| `readonly` | `boolean` | `false` | 是否为只读状态 |
| `disabled` | `boolean` | `false` | 是否禁用复选框 |
| `value` | `boolean` | `false` | 复选框的选中状态 |
| `indeterminate` | `boolean` | `false` | 半选状态（部分选择） |
| `style` | `string` | `''` | 自定义CSS样式 |
| `compact` | `boolean` | `false` | 紧凑显示模式 |
| `onclick` | `((event: MouseEvent) => void) \| null` | `null` | 点击事件处理器 |
| `onchange` | `OnChangeHandler<boolean>` | - | 值变化事件处理器 |
| `onfocus` | `((event: FocusEvent) => void) \| null` | `null` | 聚焦事件处理器 |
| `onblur` | `((event: FocusEvent) => void) \| null` | `null` | 失焦事件处理器 |
| `autoFocus` | `boolean` | `false` | 是否在组件挂载时自动聚焦 |

## 方法

| 方法 | 描述 |
|------|-----|
| `setFocus()` | 程序化地使复选框获得焦点 |

## 基本示例

### 简单复选框

```svelte
<script>
let agreed = false;
</script>

<CheckBox 
  label="我同意条款"
  bind:value={agreed}
/>

<p>状态: {agreed ? '已同意' : '未同意'}</p>
```

### 带变化处理器

```svelte
<script>
let notifications = true;

const handleNotificationChange = (value) => {
  console.log('通知设置:', value ? '启用' : '禁用');
  notifications = value;
};
</script>

<CheckBox 
  label="启用通知"
  value={notifications}
  onChange={handleNotificationChange}
/>
```

### 半选状态

```svelte
<script>
let parentChecked = false;
let parentIndeterminate = false;
let childItems = [
  { id: 1, name: '项目 1', checked: true },
  { id: 2, name: '项目 2', checked: false },
  { id: 3, name: '项目 3', checked: true }
];

$: {
  const checkedCount = childItems.filter(item => item.checked).length;
  parentChecked = checkedCount === childItems.length;
  parentIndeterminate = checkedCount > 0 && checkedCount < childItems.length;
}

const handleParentChange = (value) => {
  childItems = childItems.map(item => ({ ...item, checked: value }));
};

const handleChildChange = (id) => (value) => {
  childItems = childItems.map(item => 
    item.id === id ? { ...item, checked: value } : item
  );
};
</script>

<CheckBox 
  label="全选"
  value={parentChecked}
  indeterminate={parentIndeterminate}
  onChange={handleParentChange}
/>

{#each childItems as item}
  <div style="margin-left: 20px;">
    <CheckBox 
      label={item.name}
      value={item.checked}
      onChange={handleChildChange(item.id)}
    />
  </div>
{/each}
```

## 事件处理

```svelte
<script>
let value = false;
let focusCount = 0;
let clickCount = 0;

const handleChange = (newValue) => {
  console.log('值变化为:', newValue);
  value = newValue;
};

const handleClick = (event) => {
  clickCount++;
  console.log('复选框被点击', clickCount, '次');
};

const handleFocus = (event) => {
  focusCount++;
  console.log('复选框获得焦点');
};

const handleBlur = (event) => {
  console.log('复选框失去焦点');
};
</script>

<CheckBox 
  label="交互式复选框"
  {value}
  onChange={handleChange}
  onClick={handleClick}
  onfocus={handleFocus}
  onblur={handleBlur}
/>

<div>
  <p>当前值: {value}</p>
  <p>聚焦次数: {focusCount}</p>
  <p>点击次数: {clickCount}</p>
</div>
```

## 状态和模式

### 禁用状态

```svelte
<CheckBox 
  label="禁用未选中"
  value={false}
  disabled={true}
/>

<CheckBox 
  label="禁用已选中"
  value={true}
  disabled={true}
/>
```

### 只读状态

```svelte
<CheckBox 
  label="只读未选中"
  value={false}
  readonly={true}
/>

<CheckBox 
  label="只读已选中"
  value={true}
  readonly={true}
/>
```

### 紧凑模式

```svelte
<div style="display: flex; gap: 16px; align-items: center;">
  <CheckBox label="普通" value={true} />
  <CheckBox label="紧凑" value={true} compact={true} />
</div>
```

### 自动聚焦

```svelte
<CheckBox 
  label="自动聚焦的复选框"
  autoFocus={true}
/>
```

## 高级示例

### 表单集成

```svelte
<script>
let formData = {
  newsletter: false,
  terms: false,
  privacy: false
};

$: canSubmit = formData.terms && formData.privacy;

const handleSubmit = () => {
  if (canSubmit) {
    console.log('表单提交:', formData);
  }
};

const updateField = (field) => (value) => {
  formData = { ...formData, [field]: value };
};
</script>

<form on:submit|preventDefault={handleSubmit}>
  <div class="form-section">
    <CheckBox 
      label="订阅邮件（可选）"
      value={formData.newsletter}
      onChange={updateField('newsletter')}
    />
  </div>
  
  <div class="form-section">
    <CheckBox 
      label="我接受服务条款 *"
      value={formData.terms}
      onChange={updateField('terms')}
    />
  </div>
  
  <div class="form-section">
    <CheckBox 
      label="我接受隐私政策 *"
      value={formData.privacy}
      onChange={updateField('privacy')}
    />
  </div>
  
  <button type="submit" disabled={!canSubmit}>
    提交
  </button>
</form>

<style>
  .form-section {
    margin: 16px 0;
  }
</style>
```

### 设置面板

```svelte
<script>
let settings = {
  darkMode: false,
  notifications: true,
  autoSave: true,
  soundEffects: false
};

const updateSetting = (key) => (value) => {
  settings = { ...settings, [key]: value };
  localStorage.setItem('app-settings', JSON.stringify(settings));
};

// 组件挂载时加载设置
import { onMount } from 'svelte';

onMount(() => {
  const saved = localStorage.getItem('app-settings');
  if (saved) {
    settings = { ...settings, ...JSON.parse(saved) };
  }
});
</script>

<div class="settings-panel">
  <h3>应用设置</h3>
  
  <div class="setting-group">
    <h4>外观</h4>
    <CheckBox 
      label="深色模式"
      value={settings.darkMode}
      onChange={updateSetting('darkMode')}
    />
  </div>
  
  <div class="setting-group">
    <h4>通知</h4>
    <CheckBox 
      label="启用通知"
      value={settings.notifications}
      onChange={updateSetting('notifications')}
    />
  </div>
  
  <div class="setting-group">
    <h4>编辑器</h4>
    <CheckBox 
      label="自动保存文档"
      value={settings.autoSave}
      onChange={updateSetting('autoSave')}
    />
  </div>
  
  <div class="setting-group">
    <h4>音频</h4>
    <CheckBox 
      label="音效"
      value={settings.soundEffects}
      onChange={updateSetting('soundEffects')}
    />
  </div>
</div>

<style>
  .settings-panel {
    max-width: 400px;
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
  }
  
  .setting-group {
    margin: 20px 0;
  }
  
  .setting-group h4 {
    margin: 0 0 12px 0;
    color: #666;
    font-size: 14px;
    text-transform: uppercase;
  }
</style>
```

### 待办事项列表与全选

```svelte
<script>
let todos = [
  { id: 1, text: '买菜', completed: false },
  { id: 2, text: '遛狗', completed: true },
  { id: 3, text: '看书', completed: false },
  { id: 4, text: '给妈妈打电话', completed: true }
];

$: completedCount = todos.filter(todo => todo.completed).length;
$: allCompleted = completedCount === todos.length;
$: someCompleted = completedCount > 0 && completedCount < todos.length;

const toggleAll = (value) => {
  todos = todos.map(todo => ({ ...todo, completed: value }));
};

const toggleTodo = (id) => (completed) => {
  todos = todos.map(todo => 
    todo.id === id ? { ...todo, completed } : todo
  );
};
</script>

<div class="todo-list">
  <h3>待办事项</h3>
  
  <CheckBox 
    label={`全选 (${completedCount}/${todos.length})`}
    value={allCompleted}
    indeterminate={someCompleted}
    onChange={toggleAll}
    style="border-bottom: 1px solid #ddd; padding-bottom: 12px; margin-bottom: 12px;"
  />
  
  {#each todos as todo}
    <div class="todo-item" class:completed={todo.completed}>
      <CheckBox 
        label={todo.text}
        value={todo.completed}
        onChange={toggleTodo(todo.id)}
      />
    </div>
  {/each}
  
  <div class="todo-summary">
    已完成 {completedCount} / {todos.length} 项
  </div>
</div>

<style>
  .todo-list {
    max-width: 400px;
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 16px;
  }
  
  .todo-item {
    margin: 8px 0;
    transition: opacity 0.2s;
  }
  
  .todo-item.completed {
    opacity: 0.6;
  }
  
  .todo-summary {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid #ddd;
    font-size: 14px;
    color: #666;
    text-align: center;
  }
</style>
```

### 权限管理

```svelte
<script>
let permissions = {
  read: true,
  write: false,
  delete: false,
  admin: false
};

const updatePermission = (key) => (value) => {
  // 自动管理依赖关系
  if (key === 'admin' && value) {
    permissions = { read: true, write: true, delete: true, admin: true };
  } else if (key === 'admin' && !value) {
    permissions = { ...permissions, admin: false };
  } else if (key === 'read' && !value) {
    permissions = { read: false, write: false, delete: false, admin: false };
  } else if ((key === 'write' || key === 'delete') && value && !permissions.read) {
    permissions = { ...permissions, read: true, [key]: value };
  } else {
    permissions = { ...permissions, [key]: value };
  }
};

$: canWrite = permissions.read;
$: canDelete = permissions.read;
$: canAdmin = permissions.read && permissions.write && permissions.delete;
</script>

<div class="permissions-panel">
  <h3>用户权限</h3>
  
  <CheckBox 
    label="读取权限"
    value={permissions.read}
    onChange={updatePermission('read')}
  />
  
  <CheckBox 
    label="写入权限"
    value={permissions.write}
    disabled={!canWrite}
    onChange={updatePermission('write')}
    style="margin-left: 20px;"
  />
  
  <CheckBox 
    label="删除权限"
    value={permissions.delete}
    disabled={!canDelete}
    onChange={updatePermission('delete')}
    style="margin-left: 20px;"
  />
  
  <CheckBox 
    label="管理员"
    value={permissions.admin}
    disabled={!canAdmin}
    onChange={updatePermission('admin')}
    style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #ddd;"
  />
  
  <div class="permission-summary">
    <h4>当前访问级别：</h4>
    <p>
      {#if permissions.admin}
        管理员（完全访问）
      {:else if permissions.delete}
        编辑者（读取、写入、删除）
      {:else if permissions.write}
        贡献者（读取、写入）
      {:else if permissions.read}
        查看者（仅读取）
      {:else}
        无访问权限
      {/if}
    </p>
  </div>
</div>

<style>
  .permissions-panel {
    max-width: 350px;
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
  }
  
  .permission-summary {
    margin-top: 20px;
    padding: 16px;
    background: #f5f5f5;
    border-radius: 4px;
  }
  
  .permission-summary h4 {
    margin: 0 0 8px 0;
    font-size: 14px;
  }
  
  .permission-summary p {
    margin: 0;
    font-weight: 500;
  }
</style>
```

### 功能开关列表

```svelte
<script>
let features = [
  { id: 'beta-ui', name: 'Beta UI 功能', enabled: false, description: '尝试新的界面元素' },
  { id: 'analytics', name: '使用分析', enabled: true, description: '帮助改进应用' },
  { id: 'experiments', name: '实验性功能', enabled: false, description: '访问前沿功能' },
  { id: 'debug', name: '调试模式', enabled: false, description: '显示额外的调试信息' }
];

const toggleFeature = (id) => (enabled) => {
  features = features.map(feature => 
    feature.id === id ? { ...feature, enabled } : feature
  );
};

$: enabledCount = features.filter(f => f.enabled).length;
</script>

<div class="feature-toggles">
  <h3>功能开关 (已启用 {enabledCount} 个)</h3>
  
  {#each features as feature}
    <div class="feature-item">
      <CheckBox 
        label={feature.name}
        value={feature.enabled}
        onChange={toggleFeature(feature.id)}
      />
      <p class="feature-description">{feature.description}</p>
    </div>
  {/each}
</div>

<style>
  .feature-toggles {
    max-width: 500px;
  }
  
  .feature-item {
    margin: 16px 0;
    padding: 12px;
    border: 1px solid #e0e0e0;
    border-radius: 4px;
  }
  
  .feature-description {
    margin: 8px 0 0 24px;
    font-size: 13px;
    color: #666;
  }
</style>
```

## 程序化控制

```svelte
<script>
let checkbox;
let value = false;

const focusCheckbox = () => {
  checkbox?.setFocus();
};

const toggleValue = () => {
  value = !value;
};
</script>

<div class="controls">
  <button on:click={focusCheckbox}>聚焦复选框</button>
  <button on:click={toggleValue}>切换值</button>
</div>

<CheckBox 
  bind:this={checkbox}
  label="程序化控制"
  {value}
  onChange={(v) => value = v}
/>

<style>
  .controls {
    margin-bottom: 16px;
    display: flex;
    gap: 8px;
  }
</style>
```

## 自定义样式

```svelte
<CheckBox 
  label="自定义样式复选框"
  value={true}
  style="
    padding: 12px;
    background: #f0f8ff;
    border: 2px solid #007acc;
    border-radius: 8px;
    font-weight: 500;
  "
/>
```

## 无障碍访问

CheckBox组件包含：

- 正确的语义化`input[type="checkbox"]`元素
- 为屏幕阅读器关联的标签
- 键盘导航支持（Tab、空格键）
- 聚焦和失焦事件处理
- 禁用状态管理
- 半选状态的ARIA属性

### 最佳实践

```svelte
<!-- 良好：清晰、描述性的标签 -->
<CheckBox label="启用双重认证" />

<!-- 良好：相关复选框分组 -->
<fieldset>
  <legend>通知偏好</legend>
  <CheckBox label="邮件通知" />
  <CheckBox label="短信通知" />
  <CheckBox label="推送通知" />
</fieldset>

<!-- 良好：标明必填字段 -->
<CheckBox label="我同意服务条款 *" />
```

## 浏览器支持

在支持以下特性的所有现代浏览器中工作：
- ES6+ JavaScript
- 现代DOM API
- CSS自定义属性
- HTML5表单元素

## 性能考虑

- 高效的事件处理和适当的清理
- 响应式更新的最小重新渲染
- 轻量级DOM结构
- 优化的焦点管理