import { $, $html, $for } from "sigpro"; import { val } from "../core/utils.js"; import { tt } from "../core/i18n.js"; import { Input } from "./Input.js"; // Importamos el componente hermano /** AUTOCOMPLETE */ export const Autocomplete = (props) => { const { options = [], value, onSelect, label, placeholder, ...rest } = props; const query = $(val(value) || ""); const isOpen = $(false); const cursor = $(-1); const list = $(() => { const q = query().toLowerCase(); const data = val(options) || []; return q ? data.filter((o) => (typeof o === "string" ? o : o.label).toLowerCase().includes(q)) : data; }); const pick = (opt) => { const valStr = typeof opt === "string" ? opt : opt.value; const labelStr = typeof opt === "string" ? opt : opt.label; query(labelStr); if (typeof value === "function") value(valStr); onSelect?.(opt); isOpen(false); cursor(-1); }; const nav = (e) => { const items = list(); if (e.key === "ArrowDown") { e.preventDefault(); isOpen(true); cursor(Math.min(cursor() + 1, items.length - 1)); } else if (e.key === "ArrowUp") { e.preventDefault(); cursor(Math.max(cursor() - 1, 0)); } else if (e.key === "Enter" && cursor() >= 0) { e.preventDefault(); pick(items[cursor()]); } else if (e.key === "Escape") { isOpen(false); } }; return $html("div", { class: "relative w-full" }, [ Input({ label, placeholder: placeholder || tt("search")(), value: query, onfocus: () => isOpen(true), onblur: () => setTimeout(() => isOpen(false), 150), onkeydown: nav, oninput: (e) => { const v = e.target.value; query(v); if (typeof value === "function") value(v); isOpen(true); cursor(-1); }, ...rest, }), $html( "ul", { class: "absolute left-0 w-full menu bg-base-100 rounded-box mt-1 p-2 shadow-xl max-h-60 overflow-y-auto border border-base-300 z-50", style: () => (isOpen() && list().length ? "display:block" : "display:none"), }, [ $for( list, (opt, i) => $html("li", {}, [ $html( "a", { class: () => `block w-full ${cursor() === i ? "active bg-primary text-primary-content" : ""}`, onclick: () => pick(opt), onmouseenter: () => cursor(i), }, typeof opt === "string" ? opt : opt.label, ), ]), (opt, i) => (typeof opt === "string" ? opt : opt.value) + i, ), () => (list().length ? null : $html("li", { class: "p-2 text-center opacity-50" }, "No results")), ], ), ]); };