From 07a83b2e3db40f4a380092d6566500799b340dcd Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Fri, 21 Aug 2026 16:13:12 +0200 Subject: feat: fuzzy autocomplete for add-item input Replace the native with a custom fuzzysort-driven component (FuzzyAutocomplete) with keyboard nav and highlighted matches, preserving exact-match auto-add. Extract a unit-tested fuzzy-search helper, and gitignore .juggler/. Fix the dev DB boot failure caused by a sibling project's ambient DATABASE_URL leaking in by overriding it (file:./data.db) in mise.toml. --- src/lib/components/fuzzy-search.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/lib/components/fuzzy-search.ts (limited to 'src/lib/components/fuzzy-search.ts') diff --git a/src/lib/components/fuzzy-search.ts b/src/lib/components/fuzzy-search.ts new file mode 100644 index 0000000..31597b0 --- /dev/null +++ b/src/lib/components/fuzzy-search.ts @@ -0,0 +1,25 @@ +import fuzzysort, { type KeyResult } from 'fuzzysort'; + +export type FuzzyItem = { id: number; name: string }; + +export const FUZZ_LIMIT = 8; +export const FUZZ_THRESHOLD = 0.2; + +export type FuzzyMatch = KeyResult; + +/** Fuzzy-match `items` against `query`, ranked best-first. Empty/whitespace + * query returns no matches. Results carry `.score`, `.target`, `.highlight()` + * and `.obj` (the matched item). */ +export function matchItems( + items: FuzzyItem[], + query: string, + { + limit = FUZZ_LIMIT, + threshold = FUZZ_THRESHOLD, + }: { limit?: number; threshold?: number } = {}, +): FuzzyMatch[] { + const q = query.trim(); + if (q === '') return []; + const snap = fuzzysort.snapshot(items, { key: 'name' }); + return Array.from(fuzzysort.go(q, snap, { limit, threshold })); +} -- cgit v1.3