# MultipleSelector (Deprecated)

## Overview

Tag-style multi-select built on `cmdk` and `Popover` with search, grouping, creatable options, and badges for selections.

- ⚠️ This component is deprecated. Prefer `AppSelect` for new code.

---

## Types

```ts
// Deprecated interface. Prefer AppSelect options.
export interface Option {
  value: string;
  label: string;
  disable?: boolean;
  fixed?: boolean; // fixed option that can't be removed
  [key: string]: string | boolean | undefined; // for grouping keys
}
```

---

## Props (highlights)

| Prop                          | Type                               | Default                   | Description                                          |
| ----------------------------- | ---------------------------------- | ------------------------- | ---------------------------------------------------- | ----------------------------- |
| `value`                       | `Option[]`                         | `[]`                      | Controlled selected options.                         |
| `defaultOptions`              | `Option[]`                         | `[]`                      | Initial options to display.                          |
| `options`                     | `Option[]`                         | `undefined`               | Manually controlled options (when not using search). |
| `placeholder`                 | `string`                           | `"Cerca..."`              | Input placeholder.                                   |
| `onSearch`                    | `(q: string) => Promise<Option[]>` | `undefined`               | Async search. Debounced by `delay`.                  |
| `onSearchSync`                | `(q: string) => Option[]`          | `undefined`               | Sync search alternative.                             |
| `delay`                       | `number`                           | `500`                     | Debounce ms for `onSearch`.                          |
| `triggerSearchOnFocus`        | `boolean`                          | `false`                   | Trigger search when input focuses.                   |
| `onChange`                    | `(opts: Option[]) => void`         | `undefined`               | Fired on selection change.                           |
| `maxSelected`                 | `number`                           | `Number.MAX_SAFE_INTEGER` | Selection limit.                                     |
| `onMaxSelected`               | `(limit: number) => void`          | `undefined`               | Called when limit reached.                           |
| `groupBy`                     | `string`                           | `undefined`               | Group options by key.                                |
| `disabled`                    | `boolean`                          | `false`                   | Disable interactions.                                |
| `hidePlaceholderWhenSelected` | `boolean`                          | `true`                    | Hide placeholder when badges exist.                  |
| `selectFirstItem`             | `boolean`                          | `true`                    | Cmdk behavior workaround.                            |
| `creatable`                   | `boolean`                          | `false`                   | Allow creating new option if not found.              |
| `hideClearAllButton`          | `boolean`                          | `false`                   | Hide the clear-all icon.                             |
| `className`                   | `string`                           | `""`                      | Trigger wrapper classes.                             |
| `badgeClassName`              | `string`                           | `""`                      | Badge classes.                                       |
| `label`                       | `string                            | React.ReactNode`          | `undefined`                                          | Optional label above control. |

Also exposes `commandProps` and `inputProps` to pass through to internal `Command` and search input.

---

## Behavior

- **Search**: Use `onSearch` (async) or `onSearchSync` (sync). Debounced input.
- **Grouping**: Provide `groupBy` key to group options.
- **Creatable**: When enabled, offers "Create \"query\"" item when not found.
- **Badges**: Selected options render as removable badges. `fixed` badges cannot be removed.
- **Limits**: Enforces `maxSelected`; calls `onMaxSelected` when exceeded.
- **Clear all**: Built-in clear-all icon (hidden with `hideClearAllButton`).
- **Disabled**: Disables input and badge removal.

---

## Examples

### Default

```tsx
import { MultipleSelector } from "laif-ds";

export function DefaultMulti() {
  return (
    <div className="w-[400px]">
      <MultipleSelector
        placeholder="Seleziona dei tag..."
        defaultOptions={[
          { value: "react", label: "React" },
          { value: "typescript", label: "TypeScript" },
        ]}
      />
    </div>
  );
}
```

### Grouped Options

```tsx
import { MultipleSelector } from "laif-ds";

const frameworks = [
  { value: "react", label: "React", category: "Frontend" },
  { value: "node", label: "Node.js", category: "Backend" },
];

export function Grouped() {
  return (
    <div className="w-[400px]">
      <MultipleSelector
        placeholder="Seleziona dei framework..."
        defaultOptions={frameworks}
        groupBy="category"
      />
    </div>
  );
}
```

### Async Search

```tsx
import { MultipleSelector } from "laif-ds";

async function mockSearch(query: string) {
  await new Promise((r) => setTimeout(r, 300));
  const tags = [
    { value: "react", label: "React" },
    { value: "typescript", label: "TypeScript" },
  ];
  return tags.filter((t) =>
    t.label.toLowerCase().includes(query.toLowerCase()),
  );
}

export function AsyncSearch() {
  return (
    <div className="w-[400px]">
      <MultipleSelector
        placeholder="Cerca dei tag..."
        onSearch={mockSearch}
        delay={300}
        triggerSearchOnFocus
      />
    </div>
  );
}
```

---

## Notes

- **Use AppSelect**: Prefer `AppSelect` for multiselect scenarios.
- **A11y**: The trigger is keyboard-accessible; ensure label association when using `label`.
