import React, { useCallback, useMemo, useState, useRef, useEffect, ReactNode, } from 'react'; import { View, type TextInputProps } from 'react-native'; import { Input } from './input'; import { Card } from './card'; import { ButtonProps } from './button'; import { LoadingBar } from '../common/LoadingBar'; import { cn } from '../../lib/utils'; interface InputDropdownProps extends TextInputProps { onChangeText: (text: string) => void; items: T[]; renderItem: (item: T, onSelect: (item: T) => void) => ReactNode; filterItems: (items: T[], searchText: string) => T[]; onItemSelect?: (item: T) => void; buttonRight?: ButtonProps; isLoading?: boolean; } export function InputDropdown({ items, renderItem, filterItems, onItemSelect, buttonRight, onChangeText, onFocus, value, isLoading, className, ...inputProps }: InputDropdownProps) { const [isDropdownOpen, setIsDropdownOpen] = useState(false); const inputRef = useRef(null); const filteredItems = useMemo(() => { return filterItems(items, value || ''); }, [items, value, filterItems]); const handleInputChange = useCallback( (text: string) => { onChangeText(text); setIsDropdownOpen(true); }, [onChangeText], ); const handleInputFocus = useCallback( (event: any) => { setIsDropdownOpen(true); onFocus?.(event); }, [onFocus], ); const handleItemSelect = useCallback( (item: T) => { onItemSelect?.(item); setIsDropdownOpen(false); }, [onItemSelect], ); // Close dropdown when clicking outside useEffect(() => { const handleClickOutside = (event: any) => { if (inputRef.current && !inputRef.current.contains(event.target)) { setIsDropdownOpen(false); } }; if (isDropdownOpen) { document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; } }, [isDropdownOpen]); return ( {isDropdownOpen && (filteredItems.length > 0 || isLoading) && ( {isLoading && } {filteredItems.map((item, index) => ( {renderItem(item, handleItemSelect)} ))} )} ); }