26 lines · 750 B
import { useMemo, useState } from "react";
import { fuzzyFilter } from "~/lib/fuzzy";

const MAX_RESULTS = 50;

/** Query, filtered matches and a keyboard-movable selection over a fixed list of paths. */
export function useFuzzyFinder(paths: string[]) {
  const [query, setQuery] = useState("");
  const [selected, setSelected] = useState(0);
  const matches = useMemo(() => fuzzyFilter(query, paths, MAX_RESULTS), [query, paths]);
  const active = Math.min(selected, Math.max(matches.length - 1, 0));

  return {
    query,
    matches,
    active,
    setQuery(value: string) {
      setQuery(value);
      setSelected(0);
    },
    move(delta: number) {
      setSelected(Math.max(0, Math.min(matches.length - 1, active + delta)));
    },
  };
}