UNPKG

react-phone-input-pro

Version:

Phone number input component for react to format phone numbers according to selected countries in real time.

160 lines (159 loc) 9.03 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { useEffect, useRef, useState } from 'react'; import { c } from '../data/countries'; import React from 'react'; import { onClickOutside } from '../utils/stylingMethods'; import Arrow from './Arrow'; import { DROPDOWN_PARENT_CLASS, DROPDOWN_BUTTON_CLASS, DROPDOWN_BUTTON_FOCUS_CLASS, DROPDOWN_BUTTON_TEXT_CLASS, DROPDOWN_ARROW_PARENT_CLASS, SELECTED_FLAG_CLASS, FLAG_CLASS, LIST_CLASS, LIST_ITEM_CLASS, LIST_ITEM_BUTTON_CLASS, DROPDOWN_INPUT_PARENT_CLASS, DROPDOWN_INPUT_CLASS, NO_OPTION_CLASS, DROPDOWN_TOP_CLASS, DROPDOWN_BUTTON_OFF_CLASS, FORM_FOCUS_CLASS, SHOW_CLASS, } from '../utils/cssClassNames'; export const CountrySelector = (props) => { const selector = useRef(); const [imgErr, setImgErr] = useState(true); const [selectedOption, setSelectedOption] = useState(); const activeOption = useRef(); const shouldShowDrpDwn = useRef(true); const drpBtn = useRef(); const selectorInput = useRef(); const [search, setSearch] = useState(''); const noOptions = useRef(false); const [clickedOutside, setClickedOutside] = useState(true); const [isButtonActive, setIsButtonActive] = useState(false); useEffect(() => { const img = new Image(); img.onload = () => { setSelectedOption(props.flags === undefined || props.flags ? props.defaultCountry.fg : props.fullIsoCode ? props.defaultCountry.c : props.defaultCountry.c_sm); setImgErr(false); }; img.onerror = () => { setSelectedOption(props.fullIsoCode ? props.defaultCountry.c : props.defaultCountry.c_sm); setImgErr(true); }; img.src = c[0].fg; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { if (selector.current && props.input && drpBtn.current) { onClickOutside(selector.current, props.input, drpBtn.current, () => { setClickedOutside(true); setIsButtonActive(false); }); props.drpButton(drpBtn.current); props.list(selector.current); } }, [props]); const getSelector = () => { setClickedOutside(false); setIsButtonActive(true); if (drpBtn.current) { const offset = drpBtn.current.getBoundingClientRect(); if (offset.bottom > 500) { selector.current && shouldShowDrpDwn.current && selector.current.classList.add(DROPDOWN_TOP_CLASS); } else { selector.current && shouldShowDrpDwn.current && selector.current.classList.remove(DROPDOWN_TOP_CLASS); } } selector.current && shouldShowDrpDwn.current && selector.current.classList.toggle(SHOW_CLASS); props.input.classList.add(FORM_FOCUS_CLASS); }; const menuStyle = props.onlyCountries ? props.onlyCountries.length < 5 ? { height: 'auto', } : {} : {}; const selectOption = (country, index) => { setClickedOutside(true); changeCountry(country['f'], country['d'], country['p']); setSelectedOption((props.flags === undefined || props.flags) && !imgErr ? country['fg'] : props.fullIsoCode ? country['c'] : country['c_sm']); activeOption.current = index; selector.current && shouldShowDrpDwn.current && selector.current.classList.remove(SHOW_CLASS); }; const countrySelectorStyle = { borderRadius: '4px 0px 0px 4px' }; const changeCountry = (format, code, placeholder) => __awaiter(void 0, void 0, void 0, function* () { var _a; props.setFormat({ format, placeholder, }); (_a = props.mainInput) === null || _a === void 0 ? void 0 : _a.focus(); props.setCountryCode(code); }); const countryOptions = (ar) => { const options = props.onlyCountries ? ar.filter((country) => { var _a, _b, _c, _d; const name = country['n'].toLocaleLowerCase(); if (search) { return ((((_a = props.onlyCountries) === null || _a === void 0 ? void 0 : _a.includes(country['c'])) || ((_b = props.onlyCountries) === null || _b === void 0 ? void 0 : _b.includes(country['c_sm']))) && name.startsWith(search)); } else { return ((_c = props.onlyCountries) === null || _c === void 0 ? void 0 : _c.includes(country['c'])) || ((_d = props.onlyCountries) === null || _d === void 0 ? void 0 : _d.includes(country['c_sm'])); } }) : ar.filter((country) => { const name = country['n'].toLocaleLowerCase(); if (search) { return name.startsWith(search); } else { return country; } }); shouldShowDrpDwn.current = (options.length && options.length > 1) || search ? true : false; if (!shouldShowDrpDwn.current || props.disabled) { drpBtn.current && drpBtn.current.classList.add(DROPDOWN_BUTTON_OFF_CLASS); } noOptions.current = options.length ? false : true; return options; }; return (React.createElement("div", { className: DROPDOWN_PARENT_CLASS }, React.createElement("button", { disabled: props.disabled, className: DROPDOWN_BUTTON_CLASS, ref: (ref) => (drpBtn.current = ref), style: countrySelectorStyle, onMouseOver: () => setClickedOutside(false), onMouseOut: () => !isButtonActive && setClickedOutside(true), onClick: getSelector, type: 'button' }, React.createElement("div", { className: DROPDOWN_BUTTON_TEXT_CLASS }, (props.flags === undefined || props.flags) && !imgErr ? (React.createElement("img", { src: selectedOption, className: SELECTED_FLAG_CLASS, alt: selectedOption })) : (React.createElement("span", null, selectedOption)), (props.onlyCountries && props.onlyCountries.length < 2 && (props.onlyCountries[0] === props.defaultCountry.c_sm || props.onlyCountries[0] === props.defaultCountry.c)) || props.disabled ? ('') : (React.createElement("div", { className: DROPDOWN_ARROW_PARENT_CLASS }, React.createElement(Arrow, { color: clickedOutside ? 'rgb(108, 108, 108)' : 'rgb(0, 145, 255)' }))))), React.createElement("div", { style: menuStyle, ref: (ref) => (selector.current = ref), className: LIST_CLASS }, (props.searchOption === undefined || props.searchOption) && (React.createElement("div", { className: DROPDOWN_INPUT_PARENT_CLASS }, React.createElement("input", { type: 'search', placeholder: 'Search...', ref: (ref) => (selectorInput.current = ref), className: DROPDOWN_INPUT_CLASS, onClick: () => { drpBtn.current && drpBtn.current.classList.add(DROPDOWN_BUTTON_FOCUS_CLASS); }, onChange: (e) => { setSearch(e.currentTarget.value.toLocaleLowerCase()); } }))), React.createElement("div", { className: LIST_ITEM_CLASS }, React.createElement("div", null, countryOptions(c).map((country, index) => { return (React.createElement("button", { key: index, onClick: () => { selectOption(country, index); }, onTouchEnd: () => { drpBtn.current && drpBtn.current.classList.add(DROPDOWN_BUTTON_FOCUS_CLASS); }, className: LIST_ITEM_BUTTON_CLASS, type: 'button' }, (props.flags === undefined || props.flags) && !imgErr ? (React.createElement("img", { src: country['fg'], alt: '', className: FLAG_CLASS })) : (''), ' ', country['n'], " ", country['d'])); }), noOptions.current && React.createElement("p", { className: NO_OPTION_CLASS }, "No options")))))); };