# FilterableCheckboxGroup

## Introduction

FilterableCheckboxGroup 컴포넌트는 대량의 옵션 중에서 여러 항목을 선택할 수 있는 검색 가능한 체크박스 그룹입니다. 검색 필터링과 가상 스크롤링을 통해 많은 수의 옵션을 효율적으로 처리할 수 있으며, "Select all" 기능으로 일괄 선택이 가능합니다. 필터링, 다중 선택 폼, 설정 화면 등에서 유용하게 사용됩니다.

> 💡 **Form 구성 시 내장 prop 사용을 권장합니다**
>
> 이 컴포넌트는 `label`, `helperText` 등의 Form 요소를 자체적으로 지원합니다.
> Form을 구성할 때 Typography로 별도의 label이나 helperText를 만드는 대신, 컴포넌트의 내장 prop을 사용하세요.

```tsx
<FilterableCheckboxGroup
  label="Select Fruits"
  placeholder="Search fruits..."
  options={defaultOptions}
/>
```

| Field       | Description | Default |
| ----------- | ----------- | ------- |
| size        | —           | —       |
| label       | —           | —       |
| helperText  | —           | —       |
| required    | —           | —       |
| value       | —           | —       |
| onChange    | —           | —       |
| placeholder | —           | —       |
| options     | —           | —       |
| maxHeight   | —           | —       |

## Usage

```tsx
import { FilterableCheckboxGroup } from '@ceed/ads';

function MyComponent() {
  const [selectedValues, setSelectedValues] = useState<string[]>([]);

  const options = [
    { value: 'apple', label: 'Apple' },
    { value: 'banana', label: 'Banana' },
    { value: 'cherry', label: 'Cherry' },
  ];

  return (
    <FilterableCheckboxGroup
      label="Select Fruits"
      placeholder="Search fruits..."
      options={options}
      value={selectedValues}
      onChange={setSelectedValues}
    />
  );
}
```

## Examples

### Sizes

다양한 크기의 FilterableCheckboxGroup을 사용할 수 있습니다.

```tsx
<Stack spacing={3}>
  <FilterableCheckboxGroup {...args} size="lg" label="Large" />
  <FilterableCheckboxGroup {...args} size="md" label="Medium" />
  <FilterableCheckboxGroup {...args} size="sm" label="Small" />
</Stack>
```

### With Label

라벨을 추가할 수 있습니다.

```tsx
<FilterableCheckboxGroup
  label="Select your favorite fruits"
  placeholder="Search fruits..."
  options={defaultOptions}
/>
```

### With Helper Text

도움말 텍스트를 추가할 수 있습니다.

```tsx
<FilterableCheckboxGroup
  label="Select Fruits"
  placeholder="Search fruits..."
  helperText="You can select multiple options"
  options={defaultOptions}
/>
```

### Required Field

필수 입력 필드로 표시할 수 있습니다.

```tsx
<FilterableCheckboxGroup
  label="Required Field"
  placeholder="Search..."
  required
  helperText="This field is required"
  options={defaultOptions}
/>
```

### Custom Max Height

목록의 최대 높이를 커스터마이징할 수 있습니다.

```tsx
<Stack spacing={3}>
  <FilterableCheckboxGroup label="Custom Height (150px)" placeholder="Search..." options={defaultOptions} maxHeight={150} />
  <FilterableCheckboxGroup label="Default Height (300px)" placeholder="Search..." options={defaultOptions} />
</Stack>
```

### Long List

많은 수의 옵션을 가상 스크롤링으로 효율적으로 표시합니다.

```tsx
<FilterableCheckboxGroup
  label="Countries"
  placeholder="Search countries..."
  options={countryNames.map(name => ({
  value: name.toLowerCase().replace(/ /g, '-'),
  label: name
}))}
/>
```

### No Options

옵션이 없을 때의 상태입니다.

```tsx
<FilterableCheckboxGroup
  label="No Options Available"
  placeholder="Search..."
  options={[]}
/>
```

### Controlled

외부에서 값을 제어하는 예제입니다.

```tsx
<Stack spacing={2}>
  <FilterableCheckboxGroup label="Select Fruits" placeholder="Search fruits..." options={defaultOptions} value={value} onChange={setValue} />
  <Typography level="body-sm">
    Selected:{' '}
    {value.length > 0 ? value.map(v => defaultOptions.find(o => o.value === v)?.label).join(', ') : 'None'}
  </Typography>
</Stack>
```

### Sorting

정렬 동작을 확인할 수 있는 예제입니다. 초기 렌더링 시 선택된 항목이 먼저 표시되고, 그 다음 알파벳 순으로 정렬됩니다.

```tsx
<Stack spacing={2}>
  <Stack direction="row" spacing={1}>
    <button type="button" onClick={() => {
      setOptions([...options, {
        value: `new-${Date.now()}`,
        label: `New Item ${options.length - 11}`
      }]);
    }} style={{
      padding: '4px 12px',
      cursor: 'pointer'
    }}>
    Add New Option
  </button>
  <button type="button" onClick={() => {
    setKey(prev => prev + 1);
  }} style={{
    padding: '4px 12px',
    cursor: 'pointer'
  }}>
  Force Re-render
</button>
</Stack>
<FilterableCheckboxGroup key={key} label="Sorting Demo" placeholder="Search..." helperText="Click 'Add New Option' to test sorting when options change" options={options} value={value} onChange={setValue} />
<Typography level="body-sm" sx={{
  whiteSpace: 'pre-line'
}}>
{`Selected: ${value.length > 0 ? value.join(', ') : 'None'}\n\nOptions count: ${options.length}\n\n- Add New Option: Add new item to test sorting when options change\n- Force Re-render: Remount component to test initial sorting\n\nAlphabet items (A-Z) appear first, then numbers (1-9).`}
</Typography>
</Stack>
```

### Disabled

컴포넌트 전체 또는 특정 옵션을 비활성화할 수 있습니다.

- **컴포넌트 전체 비활성화**: `disabled` prop을 사용하여 검색 input, "Select all", 모든 옵션을 비활성화합니다.
- **특정 옵션 비활성화**: 옵션 객체의 `disabled` 속성을 사용하여 개별 옵션을 비활성화합니다.
- **"Select all" 동작**: 비활성화된 옵션은 "Select all"의 영향을 받지 않으며, 선택 상태가 유지됩니다.

```tsx
<Stack spacing={3}>
  <FilterableCheckboxGroup label="Entirely Disabled" placeholder="Search..." helperText="All inputs are disabled" options={defaultOptions.slice(0, 5)} disabled />
  <FilterableCheckboxGroup label="Partially Disabled Options" placeholder="Search..." helperText="Some options are disabled" options={disabledOptions} />
  <Stack spacing={2}>
    <FilterableCheckboxGroup label="Controlled + Partially Disabled" placeholder="Search..." helperText="Disabled options (Banana, Date) maintain their selected state" options={disabledOptions} value={controlledValue} onChange={setControlledValue} />
    <Typography level="body-sm">
      Selected: {controlledValue.length > 0 ? controlledValue.join(', ') : 'None'}
    </Typography>
    <Typography level="body-sm" sx={{
      color: 'text.secondary'
    }}>
    Try "Select all" - it will only affect enabled options (Apple, Cherry, Elderberry)
  </Typography>
</Stack>
</Stack>
```
