UNPKG

@artmajeur/react-native-paper-phone-number-input

Version:

A performant phone number input component for react-native-paper with country picker

239 lines (234 loc) 8.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CountryPicker = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativePaper = require("react-native-paper"); var _reactNativeSafeAreaContext = require("react-native-safe-area-context"); var _constants = require("./constants"); var _countries = require("./data/countries"); var _translatedCountries = _interopRequireDefault(require("./data/translatedCountries")); var _hooks = require("./hooks"); var _useDebouncedValue = require("./use-debounced-value"); var _useThemeWithFlagsFont = _interopRequireDefault(require("./useThemeWithFlagsFont")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } const CountryPicker = exports.CountryPicker = /*#__PURE__*/(0, _react.forwardRef)(({ country, setCountry, showFirstOnList, modalStyle, modalContainerStyle, includeCountries, excludeCountries, // Prpos from TextInput that needs special handling disabled, editable = true, theme, lang = 'fr', placeholder = '', searchLabel = '', // rest of the props ...rest }, ref) => { const insets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)(); const themeWithFlagsFont = (0, _useThemeWithFlagsFont.default)(theme); // States for the modal const [visible, setVisible] = (0, _react.useState)(false); const countryFlag = (0, _react.useMemo)(() => { if (country) { const matchedCountry = _countries.countries.find(c => c.code.toLocaleLowerCase() === country.toLocaleLowerCase()); return matchedCountry?.flag; } return undefined; }, [country]); // States for the searchbar const [searchQuery, setSearchQuery] = (0, _react.useState)(''); const debouncedSearchQuery = (0, _useDebouncedValue.useDebouncedValue)(searchQuery, 300); const searchbarRef = (0, _react.useRef)(null); const openModal = (0, _react.useCallback)(() => { setVisible(true); }, []); const closeModal = (0, _react.useCallback)(() => { setVisible(false); }, []); // Focus the search bar when the modal becomes visible (0, _react.useEffect)(() => { if (visible) { // We need a small delay to ensure the modal is fully animated and the search bar is rendered setTimeout(() => { searchbarRef.current?.focus(); }, 100); } }, [visible]); (0, _react.useImperativeHandle)(ref, () => ({ openCountryPicker: openModal, closeCountryPicker: closeModal }), [openModal, closeModal]); const countriesList = (0, _hooks.useCountriesList)({ showFirstOnList, includeCountries, excludeCountries }); const searchResult = (0, _hooks.useCountrySearch)({ searchQuery: debouncedSearchQuery, countriesList, lang }); const handleCountrySelect = (0, _react.useCallback)(selectedCountry => { setCountry(selectedCountry.code); closeModal(); }, [setCountry, closeModal]); const renderCountryItem = (0, _react.useCallback)(({ item }) => /*#__PURE__*/_react.default.createElement(_reactNativePaper.DataTable.Row, { onPress: () => handleCountrySelect(item), theme: theme }, /*#__PURE__*/_react.default.createElement(_reactNativePaper.DataTable.Cell, { theme: themeWithFlagsFont }, `${item.flag} ${_translatedCountries.default.getName(item.code, lang) || item.name}`)), [handleCountrySelect, theme, themeWithFlagsFont, lang]); const keyExtractor = (0, _react.useCallback)(item => item.code, []); const value = (0, _react.useMemo)(() => { if (country && countryFlag) { return `${countryFlag} ${_translatedCountries.default.getName(country, lang)}`; } return placeholder; }, [country, countryFlag, lang, placeholder]); // Dynamic styles based on theme const dynamicStyles = (0, _react.useMemo)(() => ({ searchbar: { flex: 1 }, searchbarContent: { backgroundColor: 'transparent', fontSize: 16 }, outlined: { borderRadius: 30, borderColor: theme?.dark ? '#343740' : '#CBD5E1' } }), [theme]); return /*#__PURE__*/_react.default.createElement(_reactNative.View, null, /*#__PURE__*/_react.default.createElement(_reactNativePaper.TextInput, _extends({ right: /*#__PURE__*/_react.default.createElement(_reactNativePaper.TextInput.Icon, { icon: "chevron-down" }) }, rest, { disabled: disabled, editable: editable, value: value, theme: themeWithFlagsFont })), /*#__PURE__*/_react.default.createElement(_reactNativePaper.TouchableRipple, { disabled: disabled || !editable, style: styles.ripple, onPress: openModal, theme: theme }, /*#__PURE__*/_react.default.createElement(_reactNativePaper.Text, null, " ")), /*#__PURE__*/_react.default.createElement(_reactNativePaper.Portal, { theme: theme }, /*#__PURE__*/_react.default.createElement(_reactNativePaper.Modal, { style: [styles.modal, modalStyle], contentContainerStyle: [styles.countries, { backgroundColor: themeWithFlagsFont.colors.background, paddingTop: insets.top + 16, paddingBottom: insets.bottom + 16 },, modalContainerStyle], visible: visible, onDismiss: closeModal, theme: theme }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.searchbox }, /*#__PURE__*/_react.default.createElement(_reactNativePaper.IconButton, { icon: "arrow-left", onPress: closeModal, theme: theme }), /*#__PURE__*/_react.default.createElement(_reactNativePaper.TextInput, { style: [styles.searchbar, dynamicStyles.searchbar], placeholder: searchLabel, onChangeText: setSearchQuery, value: searchQuery, ref: searchbarRef, mode: "outlined", dense: true, theme: theme, onKeyPress: ({ nativeEvent }) => { if (nativeEvent.key === 'Escape') { closeModal(); } }, selectionColor: _reactNative.Platform.select({ ios: (0, _reactNative.PlatformColor)('systemBlue'), android: (0, _reactNative.PlatformColor)('@android:color/holo_blue_light') }), cursorColor: _reactNative.Platform.select({ android: (0, _reactNative.PlatformColor)('@android:color/holo_blue_light') }), left: /*#__PURE__*/_react.default.createElement(_reactNativePaper.TextInput.Icon, { icon: "magnify", size: 20, style: styles.searchIcon }), underlineStyle: styles.searchbarUnderline, contentStyle: [styles.searchbarContent, dynamicStyles.searchbarContent], outlineStyle: [styles.outlined, dynamicStyles.outlined] })), /*#__PURE__*/_react.default.createElement(_reactNativePaper.DataTable, { style: styles.flex1 }, /*#__PURE__*/_react.default.createElement(_reactNative.FlatList, { keyboardShouldPersistTaps: "handled", data: searchResult, keyExtractor: keyExtractor, renderItem: renderCountryItem, removeClippedSubviews: true, maxToRenderPerBatch: 20, updateCellsBatchingPeriod: 50, initialNumToRender: 15, windowSize: 10 }))))); }); const styles = _reactNative.StyleSheet.create({ ripple: { position: 'absolute', top: 0, bottom: 0, left: 0, right: 0 }, flex1: { flex: _constants.isIOS ? undefined : 1 }, modal: { marginTop: undefined, marginBottom: undefined, justifyContent: undefined }, countries: { paddingHorizontal: 16, flex: _constants.isIOS ? undefined : 1, marginBottom: _constants.isIOS ? 150 : undefined, justifyContent: undefined }, searchbox: { flexDirection: 'row' }, searchbar: { flex: 1 }, searchbarContent: { backgroundColor: 'transparent' }, searchbarUnderline: { display: 'none' }, outlined: { borderRadius: 30 }, searchIcon: { alignSelf: 'center', marginTop: 15 } }); //# sourceMappingURL=CountryPicker.js.map