2022-09-22 12:20:27 +00:00
|
|
|
|
import { useState, useEffect, memo } from "react";
|
2022-09-10 09:19:49 +00:00
|
|
|
|
import { options } from "./options";
|
2022-09-22 12:20:27 +00:00
|
|
|
|
import { FixedSizeList as List } from "react-window";
|
2022-10-03 13:41:15 +00:00
|
|
|
|
import { StyledBox } from "./styled-input-phone";
|
|
|
|
|
import { InvalidFlag } from "./svg";
|
2022-09-29 12:37:33 +00:00
|
|
|
|
import PropTypes from "prop-types";
|
2022-09-22 12:20:27 +00:00
|
|
|
|
import CustomScrollbarsVirtualList from "../scrollbar/custom-scrollbars-virtual-list";
|
2022-09-10 09:19:49 +00:00
|
|
|
|
import Box from "@docspace/components/box";
|
2022-10-03 13:41:15 +00:00
|
|
|
|
import ComboBox from "@docspace/components/combobox";
|
|
|
|
|
import TextInput from "@docspace/components/text-input";
|
2022-09-14 14:17:00 +00:00
|
|
|
|
import InputBlock from "@docspace/components/input-block";
|
2022-10-03 13:41:15 +00:00
|
|
|
|
import DropDown from "@docspace/components/drop-down";
|
|
|
|
|
import DropDownItem from "@docspace/components/drop-down-item";
|
2022-10-03 09:44:39 +00:00
|
|
|
|
import Text from "@docspace/components/text";
|
|
|
|
|
|
2022-09-29 12:37:33 +00:00
|
|
|
|
export const InputPhone = memo((props) => {
|
|
|
|
|
const [country, setCountry] = useState(props.defaultCountry);
|
2022-09-14 14:17:00 +00:00
|
|
|
|
const [searchValue, setSearchValue] = useState("");
|
2022-09-22 12:20:27 +00:00
|
|
|
|
const [filteredOptions, setFilteredOptions] = useState([]);
|
2022-09-14 14:17:00 +00:00
|
|
|
|
const [isOpen, setIsOpen] = useState(false);
|
2022-09-22 15:03:03 +00:00
|
|
|
|
const [isValid, setIsValid] = useState(true);
|
2022-09-07 17:56:40 +00:00
|
|
|
|
|
2022-09-10 09:19:49 +00:00
|
|
|
|
const handleChange = (e) => {
|
2022-09-28 07:08:49 +00:00
|
|
|
|
const str = e.target.value.replace(/\s/g, "");
|
|
|
|
|
const el = options.find((option) => option.dialCode === str);
|
|
|
|
|
|
2022-09-29 12:37:33 +00:00
|
|
|
|
if (e.target.value === "") {
|
2022-10-03 06:08:22 +00:00
|
|
|
|
setCountry((prev) => ({ ...prev, dialCode: "+", icon: InvalidFlag }));
|
2022-09-29 12:37:33 +00:00
|
|
|
|
setIsValid(false);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-28 07:08:49 +00:00
|
|
|
|
if (el) {
|
2022-09-28 14:18:07 +00:00
|
|
|
|
setIsValid(true);
|
|
|
|
|
setCountry({
|
|
|
|
|
locale: el.code,
|
|
|
|
|
dialCode: el.dialCode,
|
2022-09-28 07:08:49 +00:00
|
|
|
|
mask: el.mask,
|
|
|
|
|
icon: el.flag,
|
2022-09-28 14:18:07 +00:00
|
|
|
|
});
|
2022-09-14 14:17:00 +00:00
|
|
|
|
}
|
2022-09-10 09:19:49 +00:00
|
|
|
|
};
|
2022-09-28 14:18:07 +00:00
|
|
|
|
|
|
|
|
|
const handleSearch = (e) => {
|
|
|
|
|
setSearchValue(e.target.value);
|
|
|
|
|
};
|
2022-09-10 09:19:49 +00:00
|
|
|
|
|
2022-09-22 12:20:27 +00:00
|
|
|
|
const getMask = (locale) => {
|
2022-09-28 14:18:07 +00:00
|
|
|
|
return options.find((option) => option.code === locale).mask;
|
2022-09-22 12:20:27 +00:00
|
|
|
|
};
|
|
|
|
|
|
2022-09-29 12:37:33 +00:00
|
|
|
|
const handleClick = () => {
|
|
|
|
|
setIsOpen(!isOpen), setIsValid(true);
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-22 12:20:27 +00:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (isOpen) {
|
|
|
|
|
setFilteredOptions(
|
|
|
|
|
options.filter(
|
|
|
|
|
(val) =>
|
|
|
|
|
val.name.toLowerCase().includes(searchValue) ||
|
|
|
|
|
val.dialCode.includes(searchValue)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}, [isOpen, searchValue]);
|
|
|
|
|
|
|
|
|
|
const Row = ({ data, index, style }) => {
|
|
|
|
|
const country = data[index];
|
|
|
|
|
|
2022-10-04 07:17:19 +00:00
|
|
|
|
const onClickCountrySelect = () => {
|
2022-10-03 13:41:15 +00:00
|
|
|
|
setIsOpen(!isOpen);
|
|
|
|
|
setCountry({
|
|
|
|
|
locale: country.code,
|
|
|
|
|
dialCode: country.dialCode,
|
|
|
|
|
mask: country.mask,
|
|
|
|
|
icon: country.flag,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-22 12:20:27 +00:00
|
|
|
|
return (
|
2022-10-03 13:41:15 +00:00
|
|
|
|
<DropDownItem
|
2022-09-22 12:20:27 +00:00
|
|
|
|
key={country.code}
|
2022-10-03 09:44:39 +00:00
|
|
|
|
style={style}
|
2022-09-22 12:20:27 +00:00
|
|
|
|
icon={country.flag}
|
|
|
|
|
fillIcon={false}
|
2022-10-03 13:41:15 +00:00
|
|
|
|
className="country-item"
|
|
|
|
|
data-option={country.code}
|
2022-10-04 07:17:19 +00:00
|
|
|
|
onClick={onClickCountrySelect}
|
2022-09-22 12:20:27 +00:00
|
|
|
|
>
|
2022-10-03 13:41:15 +00:00
|
|
|
|
<Text className="country-name">{country.name}</Text>
|
|
|
|
|
<Text className="country-dialcode">{country.dialCode}</Text>
|
|
|
|
|
</DropDownItem>
|
2022-09-22 12:20:27 +00:00
|
|
|
|
);
|
|
|
|
|
};
|
2022-09-15 12:52:39 +00:00
|
|
|
|
|
2022-09-07 14:53:27 +00:00
|
|
|
|
return (
|
2022-10-03 13:41:15 +00:00
|
|
|
|
<StyledBox hasError={!isValid} displayProp="flex" alignItems="center">
|
|
|
|
|
<ComboBox
|
|
|
|
|
onClick={handleClick}
|
|
|
|
|
options={[]}
|
|
|
|
|
scaled={true}
|
|
|
|
|
noBorder={true}
|
|
|
|
|
className="country-box"
|
|
|
|
|
selectedOption={country}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextInput
|
|
|
|
|
type="tel"
|
|
|
|
|
className="input-phone"
|
|
|
|
|
placeholder={props.phonePlaceholderText}
|
|
|
|
|
mask={getMask(country.locale)}
|
|
|
|
|
withBorder={false}
|
|
|
|
|
tabIndex={1}
|
|
|
|
|
value={country.dialCode}
|
|
|
|
|
onChange={handleChange}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<DropDown
|
|
|
|
|
open={isOpen}
|
|
|
|
|
clickOutsideAction={handleClick}
|
|
|
|
|
isDefaultMode={false}
|
|
|
|
|
className="drop-down"
|
|
|
|
|
manualWidth="100%"
|
|
|
|
|
>
|
|
|
|
|
<InputBlock
|
|
|
|
|
type="text"
|
|
|
|
|
iconName="static/images/search.react.svg"
|
|
|
|
|
placeholder={props.searchPlaceholderText}
|
|
|
|
|
value={searchValue}
|
2022-10-03 16:02:00 +00:00
|
|
|
|
className="search-input"
|
2022-10-03 13:41:15 +00:00
|
|
|
|
tabIndex={2}
|
|
|
|
|
scale={true}
|
|
|
|
|
onChange={handleSearch}
|
2022-09-22 15:03:03 +00:00
|
|
|
|
/>
|
2022-10-03 13:41:15 +00:00
|
|
|
|
<Box marginProp="6px 0 0">
|
|
|
|
|
{filteredOptions.length ? (
|
|
|
|
|
<List
|
|
|
|
|
itemData={filteredOptions}
|
|
|
|
|
height={108}
|
|
|
|
|
itemCount={filteredOptions.length}
|
|
|
|
|
itemSize={36}
|
|
|
|
|
outerElementType={CustomScrollbarsVirtualList}
|
|
|
|
|
width="auto"
|
|
|
|
|
>
|
|
|
|
|
{Row}
|
|
|
|
|
</List>
|
|
|
|
|
) : (
|
2022-10-03 16:02:00 +00:00
|
|
|
|
<Text textAlign="center" className="empty-message" fontSize="14px">
|
2022-10-03 13:41:15 +00:00
|
|
|
|
{props.searchEmptyMessage}
|
|
|
|
|
</Text>
|
|
|
|
|
)}
|
|
|
|
|
</Box>
|
|
|
|
|
</DropDown>
|
2022-10-03 09:44:39 +00:00
|
|
|
|
{!isValid && (
|
|
|
|
|
<Text
|
2022-10-03 13:41:15 +00:00
|
|
|
|
className="error-text"
|
2022-10-03 09:44:39 +00:00
|
|
|
|
color="#f21c0e"
|
|
|
|
|
fontSize="11px"
|
|
|
|
|
lineHeight="14px"
|
|
|
|
|
>
|
|
|
|
|
{props.errorMessage}
|
|
|
|
|
</Text>
|
|
|
|
|
)}
|
2022-10-03 13:41:15 +00:00
|
|
|
|
</StyledBox>
|
2022-09-07 14:53:27 +00:00
|
|
|
|
);
|
2022-09-22 12:20:27 +00:00
|
|
|
|
});
|
2022-09-29 12:37:33 +00:00
|
|
|
|
|
|
|
|
|
InputPhone.propTypes = {
|
|
|
|
|
/** Default selected country Russia */
|
|
|
|
|
defaultCountry: PropTypes.object.isRequired,
|
|
|
|
|
/** Text displayed on the Input placeholder */
|
|
|
|
|
phonePlaceholderText: PropTypes.string,
|
|
|
|
|
/** Text displayed on the SearchInput placeholder */
|
|
|
|
|
searchPlaceholderText: PropTypes.string,
|
|
|
|
|
/** Called when field is clicked */
|
|
|
|
|
onClick: PropTypes.func,
|
|
|
|
|
/** Called when value is changed */
|
|
|
|
|
onChange: PropTypes.func,
|
|
|
|
|
/** Gets the country mask */
|
|
|
|
|
getMask: PropTypes.func,
|
|
|
|
|
/** Text is displayed when nothing found */
|
|
|
|
|
searchEmptyMessage: PropTypes.string,
|
|
|
|
|
/** Text is displayed when invalid country dial code */
|
|
|
|
|
errorMessage: PropTypes.string,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
InputPhone.defaultProps = {
|
|
|
|
|
defaultCountry: {
|
|
|
|
|
locale: options[182].code, // default locale RU
|
|
|
|
|
dialCode: options[182].dialCode, // default dialCode +7
|
|
|
|
|
mask: options[182].mask, // default dialCode +7
|
|
|
|
|
icon: options[182].flag, // default flag Russia
|
|
|
|
|
},
|
|
|
|
|
phonePlaceholderText: "+7 XXX XXX-XX-XX",
|
|
|
|
|
searchPlaceholderText: "Search",
|
|
|
|
|
searchEmptyMessage: "Nothing found",
|
|
|
|
|
errorMessage: "Сountry code is invalid",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
InputPhone.displayName = "InputPhone";
|