import { CollectionItem , CollectionNode , useCollection } from "./useCollection" ; import { ReactNode , SyntheticEvent , useCallback , useState } from "react" ; import { getItemText } from "./getItemText" ; import { isNil } from "../../shared" ; import { reduceCollection } from "./reduceCollection" ; function isQueryMatchingItem ( query , item ) { const itemText = getItemText ( item ) ; return itemText . toLowerCase ( ) . startsWith ( query ) ; } function useNodesFiltering ( nodes ) { const [ results , setResults ] = useState < CollectionItem [ ] > ( [ ] ) ; const filter = useCallback ( ( query ) => { const cache = { } ; query = query . toLowerCase ( ) ; if ( ! isNil ( cache [ query ] ) ) { setResults ( cache [ query ] ) ; } else { const filteredNodes = reduceCollection ( nodes , item => { return isQueryMatchingItem ( query , item ) ; } ) ; cache [ query ] = filteredNodes ; setResults ( filteredNodes ) ; } } , [ nodes , setResults ] ) ; return [ results , filter ] ; } export interface UseCollectionSearchOptions { onSearch ? : ( event : SyntheticEvent , query : string ) => void ; } export function useCollectionSearch ( children , { onSearch } ) { const nodes = useCollection ( children ) ; const [ filteredNodes , filterNodes ] = useNodesFiltering ( nodes ) ; const results = ! isNil ( onSearch ) ? nodes : filteredNodes ; const search = useCallback ( ( event , query ) => { if ( ! isNil ( onSearch ) ) { onSearch ( event , query ) ; } else { filterNodes ( query ) ; } } , [ onSearch , filterNodes ] ) ; return [ results , search ] ; }