UNPKG

react-native-phone-country-picker-input

Version:
144 lines (143 loc) 7.5 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { Image, Pressable, StyleSheet, Text, TextInput, View, } from 'react-native'; import { useEffect, useState } from 'react'; import { CountryPickerModal } from './CountryPickerModal'; /** * Core component for phone number input with country picker functionality. * * @section Props * @param {PhonePickerInputProps} props - Component props. * @param {string} props.phoneValue - Current phone number value. * @param {(value: string) => void} props.onPhoneNumberValueChange - Phone number change handler. * @param {KeyboardTypeOptions} props.keyboardType - Keyboard type for input. * @param {boolean} props.disableTextInput - Disables the text input if true. * @param {string} props.defaultplaceholder - Input placeholder text. * @param {TextInputProps} props.customTextInputProps - Additional TextInput props. * * @section Country Picker * @param {boolean} props.openCountryModal - Programmatically control modal visibility. * @param {string} [props.defaultFlag='🇺🇸'] - Default flag emoji. * @param {string} [props.defaultCountryCode='+1'] - Default country dial code. * @param {(country: Country) => void} props.onSelectCountry - Country selection callback. * * @section Modal * @param {boolean} [props.customModal=false] - Use custom modal component if true. * @param {React.ReactNode} [props.customModalComponent] - Custom modal component. * * @returns {React.JSX.Element} Phone input with country picker controls. */ export const PhonePickerInputMain = ({ // Core Input phoneValue, // Controlled phone number value onPhoneNumberValueChange, // Handler for phone number changes keyboardType = 'phone-pad', // Optimized for phone number input disableTextInput = false, // Toggles phone input visibility. if true disables the phone number text input. defaultplaceholder = 'Enter phone number', // Fallback placeholder text customTextInputProps, // Extended TextInput configuration // Country Picker openCountryModal, // External modal control trigger defaultFlag = '🇺🇸', // Fallback flag when no country selected defaultCountryCode = '+1', // Initial dial code before selection onSelectCountry, // Parent notification when country changes customArrowIconComponent, // React node to render as a custom component. e.g. react-native-vector-icons. // Modal Configuration customModalComponent, // Replacement modal component. User can pass custom modal component. /** Use getAllCountries to get the array of countries then make your own modal component.*/ // Search Customization countrySearchPlaceholder, // Overrides default search placeholder otherCountrySearchTextInputProps, // Extended search input props searchIcon, // Custom search icon (string or component) otherFlatListProps, // Custom FlatList behavior props // Styling customStyles, // Style overrides for all subcomponents }) => { // Modal visibility state (can be controlled externally via openCountryModal) const [modalVisible, setModalVisible] = useState(false); // Currently selected country with defaults const [selectedCountry, setSelectedCountry] = useState({ name: '', iso2: '', dialCode: defaultCountryCode, flag: defaultFlag, }); // Sync modal state with external control. If user want to open modal programmatically from parent using prop. useEffect(() => { if (openCountryModal !== undefined) { setModalVisible(openCountryModal); } }, [openCountryModal]); // Toggle modal visibility const handleModal = () => setModalVisible(prev => !prev); // Update selected country and notify parent. Sends selected country as callback. const handleSelectCountry = (country) => { setSelectedCountry(country); onSelectCountry === null || onSelectCountry === void 0 ? void 0 : onSelectCountry(country); }; return (_jsxs(View, { style: (customStyles === null || customStyles === void 0 ? void 0 : customStyles.mainInputContainer) || styles.mainInputContainer, children: [_jsxs(Pressable, { style: ({ pressed }) => [ (customStyles === null || customStyles === void 0 ? void 0 : customStyles.flagPickerContainer) || styles.flagPickerContainer, pressed && ((customStyles === null || customStyles === void 0 ? void 0 : customStyles.customPressedStyle) || styles.pressed), ], onPress: handleModal, accessible: true, accessibilityLabel: `Selected country: ${selectedCountry.name}. Tap to change country`, children: [_jsx(Text, { style: (customStyles === null || customStyles === void 0 ? void 0 : customStyles.flagStyle) || styles.flagStyle, children: selectedCountry.flag }), !customArrowIconComponent ? (_jsx(Image, { source: require('./caretdown.png'), style: (customStyles === null || customStyles === void 0 ? void 0 : customStyles.downArrowIcon) || styles.downArrowIcon })) : (customArrowIconComponent), _jsx(Text, { style: (customStyles === null || customStyles === void 0 ? void 0 : customStyles.countryCodeText) || styles.countryCodeText, children: selectedCountry.dialCode })] }), !disableTextInput && (_jsx(TextInput, Object.assign({ style: (customStyles === null || customStyles === void 0 ? void 0 : customStyles.phoneTextInputStyle) || styles.phoneTextInput, keyboardType: keyboardType, placeholder: defaultplaceholder, value: phoneValue, onChangeText: onPhoneNumberValueChange }, customTextInputProps))), !customModalComponent ? (_jsx(CountryPickerModal, { modalVisible: modalVisible, setModalVisible: setModalVisible, openCountryModal: openCountryModal, customStyles: customStyles, otherFlatListProps: otherFlatListProps, searchIcon: searchIcon, countrySearchPlaceholder: countrySearchPlaceholder, otherCountrySearchTextInputProps: otherCountrySearchTextInputProps, setSelectedCountry: handleSelectCountry })) : (customModalComponent)] })); }; /** * Default styles for the component */ const styles = StyleSheet.create({ mainInputContainer: { width: '100%', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly', }, flagPickerContainer: { marginVertical: '5%', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 3, borderWidth: 1, borderRadius: 6, borderColor: 'rgb(156, 156, 156)', paddingVertical: 10, paddingHorizontal: 15, backgroundColor: 'rgb(221, 221, 221)', shadowColor: 'rgba(18, 18, 19, 1)', shadowOffset: { width: 1.5, height: 1.5 }, shadowOpacity: 0.25, shadowRadius: 6, }, flagStyle: { fontSize: 20, fontWeight: '400', }, countryCodeText: { fontSize: 20, fontWeight: '400', }, phoneTextInput: { width: '60%', borderRadius: 6, borderWidth: 1, borderColor: 'rgb(156, 156, 156)', marginVertical: '5%', paddingVertical: 12, paddingHorizontal: 15, paddingLeft: 16, backgroundColor: 'rgb(221, 221, 221)', fontSize: 20, fontWeight: 400, shadowColor: 'rgba(18, 18, 19, 1)', shadowOffset: { width: 1.5, height: 1.5 }, shadowOpacity: 0.25, shadowRadius: 6, }, downArrowIcon: { objectFit: 'contain', width: 30, height: 30, padding: 0, margin: 0, }, pressed: { opacity: 0.7, }, });