UNPKG

@1771technologies/lytenyte-pro

Version:

Blazingly fast headless React data grid with 100s of features.

79 lines (78 loc) 2.68 kB
import { useState, useCallback, useRef } from "react"; import { filterCompletionsByPrefix } from "./filter-completions-by-prefix.js"; export function useCompletions(completionProvider) { const [state, setState] = useState({ items: [], filteredItems: [], selectedIndex: 0, isOpen: false, isLoading: false, }); const requestIdRef = useRef(0); const fetchCompletions = useCallback(async (tokens, cursorPosition, word) => { if (!completionProvider) return; const requestId = ++requestIdRef.current; setState((prev) => ({ ...prev, isLoading: true, isOpen: true })); try { const result = await Promise.resolve(completionProvider(tokens, cursorPosition)); if (requestId !== requestIdRef.current) return; const filtered = filterCompletionsByPrefix(result, word.word); setState({ items: result, filteredItems: filtered, selectedIndex: 0, isOpen: filtered.length > 0, isLoading: false, }); } catch { if (requestId !== requestIdRef.current) return; setState((prev) => ({ ...prev, isOpen: false, isLoading: false, })); } }, [completionProvider]); const updateFilter = useCallback((prefix) => { setState((prev) => { const filtered = filterCompletionsByPrefix(prev.items, prefix); return { ...prev, filteredItems: filtered, selectedIndex: 0, isOpen: filtered.length > 0, }; }); }, []); const navigate = useCallback((direction) => { setState((prev) => { if (prev.filteredItems.length === 0) return prev; const delta = direction === "down" ? 1 : -1; const count = prev.filteredItems.length; const nextIndex = (prev.selectedIndex + delta + count) % count; return { ...prev, selectedIndex: nextIndex }; }); }, []); const dismiss = useCallback(() => { setState((prev) => ({ ...prev, isOpen: false, isLoading: false, selectedIndex: 0, })); }, []); const selectedItem = state.isOpen && state.filteredItems.length > 0 ? state.filteredItems[state.selectedIndex] : null; return { ...state, selectedItem, fetchCompletions, updateFilter, navigate, dismiss, }; }