Externalize the whole search with a searchCallback — the library stays lean
Set el.searchCallback (JS) to delegate the entire search to your own engine — here, a FlexSearch index.
The built-in search is a lean case-insensitive substring match. When you need
fuzzy / partial / accent-insensitive / ranked matching, don't bloat the component —
externalize the whole search via searchCallback and back it with your own index. Here that's
FlexSearch (the same indexer
@keenmate/web-treeview uses), loaded client-side. It is never part of the
keen_web_multiselect bundle. From LiveView you can also handle search server-side
via the hook's search event — this page shows the client-side route.
// FlexSearch lives entirely in your app — never in the multiselect bundle.
import FlexSearch, { Charset } from "https://esm.sh/flexsearch@0.8.212";
const index = new FlexSearch.Index({ tokenize: "full", encoder: Charset.Normalize });
el.options.forEach((o, i) => index.add(i, `${o.label} ${o.value} ${o.full_title}`));
el.searchCallback = (term) =>
(index.search(term, { limit: 80 }) || []).map((i) => el.options[i]);
FlexSearch Charset.Normalize folds accents; tokenize: "full" matches partial tokens.
Cities with accented names. Try zurich → Zürich, sao →
São Paulo, krak → Kraków, munch → München.
The built-in substring search would miss all of these.
External search now composes with tree mode — matches keep their ancestors, and the index covers title + code + breadcrumb.
The whole ISCO-08 occupation tree, searched through FlexSearch. The component rebuilds the hierarchy from
the returned matches, keeping each match's ancestors so indentation stays coherent. The
index covers each occupation's title, ISCO code, and full breadcrumb — search
2211 non, welder, or health. Only unit groups (leaves) are selectable.
(pick an option anywhere on this page)