# OptionsMultiSelect

A multi-selection dropdown component that allows users to select multiple options from a predefined list, displaying selected items as removable tags.

## Features

- **Multiple Selection**: Select multiple options from a dropdown list
- **Tag Display**: Show selected items as removable tags with customizable styling
- **Checkbox Interface**: Intuitive checkbox-based selection in dropdown
- **Customizable Tags**: Different tag variants (borderless, border, round) and colors
- **Option Control**: Hide or disable specific options
- **Search Integration**: Works with CommonPicker for consistent behavior
- **Focus Management**: Proper focus handling and keyboard navigation
- **Display Modes**: Support for edit and view modes
- **Value Management**: Flexible delimiter-based value storage
- **Empty State**: Customizable placeholder and empty text

## Installation

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

## Basic Usage

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  
  let selectedValues = '';
  let options = [
    { code: 'JS', text: 'JavaScript' },
    { code: 'TS', text: 'TypeScript' },
    { code: 'PY', text: 'Python' },
    { code: 'GO', text: 'Go' }
  ];
</script>

<OptionsMultiSelect 
  {options} 
  bind:value={selectedValues}
/>
```

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `value` | `string` | `''` | Selected values as delimiter-separated string |
| `options` | `Array<any>` | `[]` | Array of option objects |
| `keyField` | `string` | `'code'` | Property name for option keys |
| `textField` | `string` | `'text'` | Property name for option display text |
| `delimiter` | `string` | `';'` | Delimiter for separating multiple values |
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Visual style variant |
| `compact` | `boolean` | `false` | Enables compact display mode |
| `disabled` | `boolean` | `false` | Disables the component |
| `readonly` | `boolean` | `false` | Makes the component read-only |
| `style` | `string` | `''` | Custom CSS styles |
| `placeholder` | `string` | `''` | Placeholder text when no items selected |
| `emptyText` | `string` | `''` | Text to show when no items selected (overrides placeholder) |
| `disableOptions` | `Array<string>` | `[]` | Keys of options to disable |
| `hideOptions` | `Array<string>` | `[]` | Keys of options to hide |
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Edit or view mode |
| `menu$height` | `number` | `0` | Maximum height of dropdown menu |
| `tagColor` | `string` | `''` | Color variant for tags |
| `tagVariant` | `'borderless' \| 'border' \| 'round'` | `'border'` | Tag visual style |
| `onchange` | `OnChangeHandler<Array<string>>` | `null` | Change event handler |
| `onfocus` | `(() => void) \| null` | `null` | Focus event handler |
| `onblur` | `(() => void) \| null` | `null` | Blur event handler |

### Methods

| Method | Description |
|--------|-------------|
| `setFocus()` | Programmatically focus the component |

## Examples

### Programming Languages Selector

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  import FormField from '@ticatec/uniface-element/FormField';
  
  let languages = '';
  let programmingLanguages = [
    { code: 'JS', text: 'JavaScript' },
    { code: 'TS', text: 'TypeScript' },
    { code: 'PY', text: 'Python' },
    { code: 'JAVA', text: 'Java' },
    { code: 'CS', text: 'C#' },
    { code: 'GO', text: 'Go' },
    { code: 'RUST', text: 'Rust' },
    { code: 'PHP', text: 'PHP' }
  ];
  
  function handleLanguageChange(selected) {
    console.log('Selected languages:', selected);
  }
</script>

<FormField label="Programming Languages">
  <OptionsMultiSelect 
    options={programmingLanguages}
    bind:value={languages}
    variant="outlined"
    tagColor="1"
    tagVariant="round"
    placeholder="Select programming languages"
    onchange={handleLanguageChange}
  />
</FormField>
```

### Skills Assessment

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  
  let selectedSkills = '';
  let skills = [
    { code: 'FE', text: 'Frontend Development' },
    { code: 'BE', text: 'Backend Development' },
    { code: 'DB', text: 'Database Design' },
    { code: 'DEVOPS', text: 'DevOps' },
    { code: 'UI', text: 'UI/UX Design' },
    { code: 'TEST', text: 'Testing' },
    { code: 'MOBILE', text: 'Mobile Development' },
    { code: 'ML', text: 'Machine Learning' }
  ];
  
  let disabledSkills = ['ML']; // Machine Learning temporarily unavailable
  
  $: selectedArray = selectedSkills ? selectedSkills.split(';') : [];
</script>

<div class="skills-selector">
  <h3>Technical Skills</h3>
  <OptionsMultiSelect 
    options={skills}
    bind:value={selectedSkills}
    variant="filled"
    tagColor="2"
    tagVariant="border"
    disableOptions={disabledSkills}
    placeholder="Select your technical skills"
    menu$height={200}
  />
  
  <div class="selected-count">
    Selected: {selectedArray.length} skill{selectedArray.length !== 1 ? 's' : ''}
  </div>
</div>
```

### Event Categories Filter

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  
  let filterCategories = '';
  let eventCategories = [
    { id: 'CONF', name: 'Conferences' },
    { id: 'WORK', name: 'Workshops' },
    { id: 'MEET', name: 'Meetups' },
    { id: 'WEB', name: 'Webinars' },
    { id: 'HACK', name: 'Hackathons' },
    { id: 'NET', name: 'Networking' },
    { id: 'TRAIN', name: 'Training' },
    { id: 'EXPO', name: 'Exhibitions' }
  ];
  
  let hiddenCategories = ['EXPO']; // Not available in current region
  
  function applyFilter(categories) {
    console.log('Filtering events by categories:', categories);
    // Apply filter logic here
  }
</script>

<div class="event-filter">
  <OptionsMultiSelect 
    options={eventCategories}
    keyField="id"
    textField="name"
    bind:value={filterCategories}
    variant="outlined"
    tagColor="3"
    tagVariant="borderless"
    hideOptions={hiddenCategories}
    placeholder="Filter by event categories"
    onchange={applyFilter}
  />
</div>
```

### Team Assignment

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  
  let assignedMembers = '';
  let teamMembers = [
    { userId: '001', fullName: 'Alice Johnson' },
    { userId: '002', fullName: 'Bob Smith' },
    { userId: '003', fullName: 'Carol Davis' },
    { userId: '004', fullName: 'David Wilson' },
    { userId: '005', fullName: 'Eva Brown' },
    { userId: '006', fullName: 'Frank Miller' }
  ];
  
  let unavailableMembers = ['003', '005']; // On vacation
  
  function handleAssignment(members) {
    console.log('Assigned team members:', members);
    // Send assignment notification
  }
</script>

<div class="team-assignment">
  <label>Assign Team Members</label>
  <OptionsMultiSelect 
    options={teamMembers}
    keyField="userId"
    textField="fullName"
    bind:value={assignedMembers}
    variant="outlined"
    tagColor="4"
    tagVariant="round"
    disableOptions={unavailableMembers}
    delimiter=","
    placeholder="Select team members for this task"
    onchange={handleAssignment}
  />
</div>
```

### Product Features Selection

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  
  let selectedFeatures = '';
  let productFeatures = [
    { feature: 'AUTH', description: 'User Authentication' },
    { feature: 'DASHBOARD', description: 'Dashboard Analytics' },
    { feature: 'REPORTS', description: 'Custom Reports' },
    { feature: 'API', description: 'API Integration' },
    { feature: 'EXPORT', description: 'Data Export' },
    { feature: 'NOTIFICATIONS', description: 'Push Notifications' },
    { feature: 'BACKUP', description: 'Automated Backup' },
    { feature: 'MULTI_LANG', description: 'Multi-language Support' }
  ];
  
  let isReadonly = false;
  
  function toggleReadonly() {
    isReadonly = !isReadonly;
  }
  
  function calculatePrice(features) {
    const featurePrices = {
      'AUTH': 10, 'DASHBOARD': 25, 'REPORTS': 20, 'API': 15,
      'EXPORT': 10, 'NOTIFICATIONS': 12, 'BACKUP': 18, 'MULTI_LANG': 8
    };
    
    return features.reduce((total, feature) => total + (featurePrices[feature] || 0), 0);
  }
  
  $: selectedArray = selectedFeatures ? selectedFeatures.split(';') : [];
  $: totalPrice = calculatePrice(selectedArray);
</script>

<div class="product-config">
  <h3>Product Configuration</h3>
  
  <OptionsMultiSelect 
    options={productFeatures}
    keyField="feature"
    textField="description"
    bind:value={selectedFeatures}
    variant="filled"
    tagColor="5"
    tagVariant="border"
    {readonly}
    placeholder="Select product features"
    menu$height={250}
  />
  
  <div class="config-summary">
    <p>Selected Features: {selectedArray.length}</p>
    <p>Total Price: ${totalPrice}/month</p>
    <button on:click={toggleReadonly}>
      {isReadonly ? 'Edit' : 'Lock'} Configuration
    </button>
  </div>
</div>
```

### Survey Interests

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  
  let interests = '';
  let surveyOptions = [
    { code: 'TECH', text: 'Technology' },
    { code: 'HEALTH', text: 'Health & Fitness' },
    { code: 'TRAVEL', text: 'Travel' },
    { code: 'FOOD', text: 'Food & Cooking' },
    { code: 'SPORTS', text: 'Sports' },
    { code: 'MUSIC', text: 'Music' },
    { code: 'ART', text: 'Arts & Culture' },
    { code: 'BOOKS', text: 'Books & Literature' },
    { code: 'GAMES', text: 'Gaming' },
    { code: 'FINANCE', text: 'Personal Finance' }
  ];
  
  function handleInterestChange(selected) {
    console.log('User interests updated:', selected);
    // Save to user profile
  }
  
  function handleFocus() {
    console.log('Survey section focused');
  }
  
  function handleBlur() {
    console.log('Survey section blurred');
  }
</script>

<div class="survey-section">
  <h3>What are you interested in?</h3>
  <p>Select all topics that interest you (minimum 3, maximum 7)</p>
  
  <OptionsMultiSelect 
    options={surveyOptions}
    bind:value={interests}
    variant="outlined"
    tagColor="6"
    tagVariant="round"
    placeholder="Choose your interests"
    emptyText="No interests selected yet"
    onchange={handleInterestChange}
    onfocus={handleFocus}
    onblur={handleBlur}
  />
</div>
```

### Compact Table Usage

```svelte
<script>
  import OptionsMultiSelect from '@ticatec/uniface-element/OptionsMultiSelect';
  
  let permissionOptions = [
    { code: 'READ', text: 'Read' },
    { code: 'WRITE', text: 'Write' },
    { code: 'DELETE', text: 'Delete' },
    { code: 'ADMIN', text: 'Admin' }
  ];
  
  let users = [
    { id: 1, name: 'John Doe', permissions: 'READ;WRITE' },
    { id: 2, name: 'Jane Smith', permissions: 'READ;WRITE;DELETE' },
    { id: 3, name: 'Admin User', permissions: 'READ;WRITE;DELETE;ADMIN' }
  ];
  
  function updatePermissions(userId, permissions) {
    const user = users.find(u => u.id === userId);
    if (user) {
      user.permissions = permissions.join(';');
      users = [...users];
    }
  }
</script>

<table class="permissions-table">
  <thead>
    <tr>
      <th>User</th>
      <th>Permissions</th>
    </tr>
  </thead>
  <tbody>
    {#each users as user}
      <tr>
        <td>{user.name}</td>
        <td>
          <OptionsMultiSelect 
            options={permissionOptions}
            value={user.permissions}
            compact
            variant="outlined"
            tagColor="7"
            tagVariant="borderless"
            onchange={(perms) => updatePermissions(user.id, perms)}
          />
        </td>
      </tr>
    {/each}
  </tbody>
</table>
```

## Tag Styling

The component supports different tag variants and colors:

### Tag Variants
- `borderless`: Clean tags without borders
- `border`: Tags with visible borders
- `round`: Rounded pill-style tags

### Tag Colors
Use color strings (e.g., "1", "2", "3") to apply different color schemes to tags.

## Best Practices

1. **Option Management**: Keep option lists focused and relevant
2. **Performance**: Consider virtualizing for very large option lists
3. **Accessibility**: Provide clear labels and descriptions
4. **Validation**: Implement min/max selection limits when needed
5. **User Experience**: Use appropriate tag styling for your design system
6. **Data Format**: Choose delimiters that won't conflict with your data
7. **State Management**: Handle loading states for dynamic options

## Styling

```css
.options-popover {
  max-height: 300px;
  overflow-y: auto;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  background: white;
}

.option-item {
  padding: 8px 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.option-item:hover {
  background-color: #f5f5f5;
}

.option-item.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
```

## Accessibility

- Full keyboard navigation support
- ARIA labels and roles for screen readers
- Focus management and visual indicators
- High contrast mode compatibility
- Checkbox accessibility standards

## Related Components

- [OptionsSelect](../options-select/README.md) - For single option selection
- [Tag](../tag/README.md) - For individual tag styling
- [FormField](../form-field/README.md) - For form layout and labels
- [CommonPicker](../common/README.md) - Base picker functionality