import React, { useState, useEffect, useCallback, useMemo } from "react"; import { View, TouchableOpacity, StyleSheet, StyleProp, TextStyle, Keyboard, FlatList, ViewStyle, } from "react-native"; import { BottomSheetFlatList } from "@gorhom/bottom-sheet"; import { useTheme } from "../../theme"; import { iso2ToFlagEmoji } from "../../utils/flags"; import { Country } from "./PhoneInput"; import { allCountries } from "country-telephone-data"; import CustomInput from "./Input"; import { ThemedText as Text } from "../ui"; interface CountryPickerViewProps { countries?: Country[]; onSelectCountry: (c: Country) => void; listTitle: string; listTitleStyle?: StyleProp; countryNameStyle?: StyleProp; countryCodeStyle?: StyleProp; searchPlaceholder?: string; isNative?: boolean; style?: StyleProp; } export const DEFAULT_COUNTRIES: Country[] = allCountries.map((c) => ({ code: `+${c.dialCode}`, iso2: c.iso2, name: c.name, })); const CountryRow = React.memo( ({ item, onSelectCountry, nameStyle, codeStyle, }: { item: Country; onSelectCountry: (c: Country) => void; nameStyle: StyleProp; codeStyle: StyleProp; }) => { const handlePress = () => { Keyboard.dismiss(); // Dismiss keyboard on selection onSelectCountry(item); }; return ( {iso2ToFlagEmoji(item.iso2)} {item.name} {item.code} ); } ); const CountryPickerView = ({ countries = DEFAULT_COUNTRIES, onSelectCountry, listTitle, listTitleStyle, countryNameStyle, countryCodeStyle, searchPlaceholder = "Search...", isNative, style }: CountryPickerViewProps) => { const { theme } = useTheme(); const [searchQuery, setSearchQuery] = useState(""); const [filteredCountries, setFilteredCountries] = useState(countries); useEffect(() => { const lowercasedQuery = searchQuery.toLowerCase().trim(); if (lowercasedQuery === "") { setFilteredCountries(countries); } else { const newFilteredData = countries.filter( (country) => country.name.toLowerCase().includes(lowercasedQuery) || country.code.includes(lowercasedQuery) ); setFilteredCountries(newFilteredData); } }, [searchQuery, countries]); const memoizedNameStyle = useMemo( () => [styles.countryName, { color: theme.text }, countryNameStyle], [theme.text, countryNameStyle] ); const memoizedCodeStyle = useMemo( () => [styles.countryCode, { color: theme.helper }, countryCodeStyle], [theme.helper, countryCodeStyle] ); const renderCountry = useCallback( ({ item }: { item: Country }) => ( ), [onSelectCountry, memoizedNameStyle, memoizedCodeStyle] ); const FlatListComponent = isNative ? FlatList : BottomSheetFlatList return ( {listTitle} c.iso2} renderItem={renderCountry} contentContainerStyle={{ paddingBottom: 16 }} initialNumToRender={15} maxToRenderPerBatch={10} nestedScrollEnabled={isNative} showsVerticalScrollIndicator={false} keyboardShouldPersistTaps="handled" ListEmptyComponent={ No countries found. } /> ); }; const styles = StyleSheet.create({ popup: { flex: 1, width: "100%", paddingHorizontal: 16, }, popupTitle: { fontSize: 18, fontWeight: "600", marginBottom: 12, paddingTop: 16, }, searchInputContainer: { marginBottom: 12, }, countryRow: { flexDirection: "row", alignItems: "center", paddingVertical: 12, // height: 56, }, flag: { fontSize: 22, }, countryText: { marginLeft: 12, flex: 1, }, countryName: { fontSize: 16, }, countryCode: { fontSize: 14, }, emptyListContainer: { paddingVertical: 40, alignItems: "center", }, emptyListText: { fontSize: 16, }, }); export default CountryPickerView;