@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
JavaScript
"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