All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 4s
277 lines
7.9 KiB
Markdown
277 lines
7.9 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` | `'Buscar...'` | 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.
|
||
|
||
## 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"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```js
|
||
const { Autocomplete, Mount } = window;
|
||
|
||
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"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```js
|
||
const { Autocomplete, Div, Mount } = window;
|
||
|
||
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-info mt-4" },
|
||
() => `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"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```js
|
||
const { Autocomplete, Div, Mount } = window;
|
||
|
||
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-success mt-4" },
|
||
`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"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```js
|
||
const { Autocomplete, Select, SelectItems, Div, Mount } = window;
|
||
|
||
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",
|
||
],
|
||
};
|
||
|
||
const options = [
|
||
{ value: "all", label: "All items" },
|
||
{ value: "fruits", label: "Fruits" },
|
||
{ value: "vegetables", label: "Vegetables" },
|
||
];
|
||
|
||
const handleFilterChange = (e) => {
|
||
filterType(e.target.value);
|
||
selected("");
|
||
setTimeout(() => selected(""), 300);
|
||
};
|
||
|
||
return Div({ class: "flex flex-col gap-4 w-full" }, [
|
||
Select(
|
||
{
|
||
class: "select select-bordered w-full",
|
||
value: filterType,
|
||
onchange: handleFilterChange,
|
||
},
|
||
SelectItems({ items: options }),
|
||
),
|
||
Div({ key: () => filterType() }, [
|
||
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"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```js
|
||
const { Autocomplete, Div, Mount } = window;
|
||
|
||
const VariantsDemo = () => {
|
||
const colors = [
|
||
"Red",
|
||
"Blue",
|
||
"Green",
|
||
"Yellow",
|
||
"Purple",
|
||
"Orange",
|
||
"Pink",
|
||
"Brown",
|
||
"Black",
|
||
"White",
|
||
];
|
||
|
||
return Div({ class: "flex flex-col gap-4" }, [
|
||
Div({ class: "font-bold" }, "Primary"),
|
||
Autocomplete({
|
||
class: "input-primary",
|
||
items: colors,
|
||
value: $(""),
|
||
placeholder: "Search colors...",
|
||
}),
|
||
Div({ class: "font-bold mt-2" }, "Secondary"),
|
||
Autocomplete({
|
||
class: "input-secondary",
|
||
items: colors,
|
||
value: $(""),
|
||
placeholder: "Search colors...",
|
||
}),
|
||
Div({ class: "font-bold mt-2" }, "Ghost"),
|
||
Autocomplete({
|
||
class: "input-ghost",
|
||
items: colors,
|
||
value: $(""),
|
||
placeholder: "Search colors...",
|
||
}),
|
||
]);
|
||
};
|
||
Mount(VariantsDemo, "#demo-variants");
|
||
```
|