laif-ds
Version:
Design System di Laif con componenti React basati su principi di Atomic Design
147 lines (116 loc) • 6 kB
Markdown
# 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`.