224 lines
6.4 KiB
Markdown
224 lines
6.4 KiB
Markdown
# Autocomplete
|
||
|
||
Searchable dropdown with autocomplete functionality, keyboard navigation, and reactive items.
|
||
|
||
## Tag
|
||
|
||
`Autocomplete`
|
||
|
||
## Props
|
||
|
||
| Prop | Type | Default | Description |
|
||
| :--- | :--- | :--- | :--- |
|
||
| `class` | `string` | `''` | Additional CSS classes for the container |
|
||
| `items` | `Array<string \| {value: string, label: string}> \| Signal` | `[]` | Items to search from |
|
||
| `value` | `string \| Signal<string>` | `''` | Selected value (reactive) |
|
||
| `onSelect` | `function(item)` | `-` | Called when an option is selected |
|
||
| `label` | `string` | `-` | Label text for the input |
|
||
| `placeholder` | `string` | `'Search...'` | Placeholder text |
|
||
|
||
## Styling
|
||
|
||
Autocomplete wraps a **daisyUI Input component** internally. All Input styling classes work:
|
||
|
||
| Category | Keywords | Description |
|
||
| :--- | :--- | :--- |
|
||
| Color | `input-primary`, `input-secondary`, `input-accent`, `input-ghost`, `input-info`, `input-success`, `input-warning`, `input-error` | Input color variants |
|
||
| Size | `input-xs`, `input-sm`, `input-md`, `input-lg` | Input scale |
|
||
| Style | `input-bordered` (default), `input-ghost` | Visual style variants |
|
||
|
||
> For further details, check the [daisyUI Input Documentation](https://daisyui.com/components/input) – Full reference for CSS classes.
|
||
|
||
### Example
|
||
|
||
```javascript
|
||
Autocomplete({
|
||
class: "input-primary input-lg",
|
||
items: fruits,
|
||
value: selected,
|
||
onSelect: (value) => selected(value)
|
||
});
|
||
// Applies: primary color, large size
|
||
```
|
||
|
||
## Live Examples
|
||
|
||
### Basic Autocomplete
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-basic" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
const BasicDemo = () => {
|
||
const selected = $('');
|
||
const fruits = ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry', 'Mango', 'Pineapple', 'Watermelon'];
|
||
|
||
return Autocomplete({
|
||
items: fruits,
|
||
value: selected,
|
||
onSelect: (value) => selected(value)
|
||
});
|
||
};
|
||
$mount(BasicDemo, '#demo-basic');
|
||
```
|
||
|
||
### With Objects
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-objects" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-col gap-4"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
const ObjectsDemo = () => {
|
||
const selected = $('');
|
||
const selectedLabel = $('');
|
||
|
||
const countries = [
|
||
{ value: 'mx', label: 'Mexico' },
|
||
{ value: 'us', label: 'United States' },
|
||
{ value: 'ca', label: 'Canada' },
|
||
{ value: 'br', label: 'Brazil' },
|
||
{ value: 'ar', label: 'Argentina' },
|
||
{ value: 'es', label: 'Spain' }
|
||
];
|
||
|
||
return Div({ class: 'flex flex-col gap-4 w-full' }, [
|
||
Autocomplete({
|
||
items: countries,
|
||
value: selectedLabel,
|
||
onSelect: (item) => {
|
||
const selectedItem = typeof item === 'string'
|
||
? countries.find(c => c.label === item)
|
||
: item;
|
||
selected(selectedItem?.value || '');
|
||
selectedLabel(selectedItem?.label || '');
|
||
}
|
||
}),
|
||
Div({ class: 'alert alert-success' }, [
|
||
() => `Selected: ${selected()} - ${selectedLabel()}`
|
||
])
|
||
]);
|
||
};
|
||
$mount(ObjectsDemo, '#demo-objects');
|
||
```
|
||
|
||
### With Reactive Display
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-reactive" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
const ReactiveDemo = () => {
|
||
const selected = $('');
|
||
|
||
const programmingLanguages = [
|
||
'JavaScript', 'Python', 'Java', 'C++', 'Ruby', 'Go', 'Rust', 'TypeScript', 'Swift', 'Kotlin'
|
||
];
|
||
|
||
return Div({ class: 'flex flex-col gap-4 w-full' }, [
|
||
Autocomplete({
|
||
items: programmingLanguages,
|
||
value: selected,
|
||
onSelect: (value) => selected(value)
|
||
}),
|
||
() => selected() ? Div({ class: 'alert alert-info' }, [
|
||
`You selected: ${selected()}`
|
||
]) : null
|
||
]);
|
||
};
|
||
$mount(ReactiveDemo, '#demo-reactive');
|
||
```
|
||
|
||
### Dynamic Items
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-dynamic" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
const DynamicDemo = () => {
|
||
const selected = $('');
|
||
const filterType = $('all');
|
||
|
||
const allItems = {
|
||
fruits: ['Apple', 'Banana', 'Orange', 'Mango'],
|
||
vegetables: ['Carrot', 'Broccoli', 'Spinach', 'Potato'],
|
||
all: ['Apple', 'Banana', 'Orange', 'Mango', 'Carrot', 'Broccoli', 'Spinach', 'Potato']
|
||
};
|
||
|
||
return Div({ class: 'flex flex-col gap-4 w-full' }, [
|
||
Select({
|
||
items: [
|
||
{ value: 'all', label: 'All items' },
|
||
{ value: 'fruits', label: 'Fruits' },
|
||
{ value: 'vegetables', label: 'Vegetables' }
|
||
],
|
||
value: filterType,
|
||
onchange: (e) => filterType(e.target.value)
|
||
}),
|
||
Autocomplete({
|
||
items: () => allItems[filterType()],
|
||
value: selected,
|
||
onSelect: (value) => selected(value)
|
||
})
|
||
]);
|
||
};
|
||
$mount(DynamicDemo, '#demo-dynamic');
|
||
```
|
||
|
||
### All Variants
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-col gap-4"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
const VariantsDemo = () => {
|
||
const colors = ['Red', 'Blue', 'Green', 'Yellow', 'Purple', 'Orange', 'Pink', 'Brown', 'Black', 'White'];
|
||
|
||
return Div({ class: 'flex flex-col gap-4' }, [
|
||
Div({}, [
|
||
Autocomplete({
|
||
class: 'input-primary',
|
||
items: colors,
|
||
value: $(''),
|
||
placeholder: 'Search colors...'
|
||
})
|
||
]),
|
||
Div({}, [
|
||
Autocomplete({
|
||
class: 'input-secondary',
|
||
items: colors,
|
||
value: $(''),
|
||
placeholder: 'Search colors...'
|
||
})
|
||
]),
|
||
Div({}, [
|
||
Autocomplete({
|
||
class: 'input-ghost',
|
||
items: colors,
|
||
value: $(''),
|
||
placeholder: 'Search colors...'
|
||
})
|
||
])
|
||
]);
|
||
};
|
||
$mount(VariantsDemo, '#demo-variants');
|
||
``` |