DocSpace-client/packages/components/input-phone/index.js

192 lines
5.2 KiB
JavaScript
Raw Normal View History

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-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-09-14 14:17:00 +00:00
import InputBlock from "@docspace/components/input-block";
2022-09-22 12:20:27 +00:00
2022-09-15 12:52:39 +00:00
import {
StyledBox,
StyledComboBox,
StyledInput,
StyledDropDown,
StyledDropDownItem,
2022-09-22 12:20:27 +00:00
StyledText,
2022-09-15 12:52:39 +00:00
CountryName,
CountryDialCode,
2022-09-22 15:03:03 +00:00
ErrorText,
2022-09-15 12:52:39 +00:00
} from "./styled-input-phone";
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 === "") {
setCountry((prev) => ({ ...prev, dialCode: "+" }));
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];
return (
<StyledDropDownItem
key={country.code}
style={{ ...style }}
data-option={country.code}
icon={country.flag}
fillIcon={false}
onClick={() => {
setIsOpen(!isOpen);
setCountry({
locale: country.code,
dialCode: country.dialCode,
2022-09-29 12:37:33 +00:00
mask: country.mask,
2022-09-22 12:20:27 +00:00
icon: country.flag,
});
}}
>
<CountryName>{country.name}</CountryName>
<CountryDialCode>{country.dialCode}</CountryDialCode>
</StyledDropDownItem>
);
};
2022-09-15 12:52:39 +00:00
2022-09-07 14:53:27 +00:00
return (
2022-09-22 15:03:03 +00:00
<>
2022-09-29 12:37:33 +00:00
<StyledBox hasError={!isValid}>
2022-09-22 12:20:27 +00:00
<Box>
2022-09-22 15:03:03 +00:00
<StyledComboBox
2022-09-29 12:37:33 +00:00
onClick={handleClick}
2022-09-22 15:03:03 +00:00
options={[]}
scaled={true}
noBorder={true}
selectedOption={country}
/>
2022-09-22 12:20:27 +00:00
</Box>
2022-09-22 15:03:03 +00:00
<StyledInput
type="tel"
2022-09-29 12:37:33 +00:00
placeholder={props.phonePlaceholderText}
2022-09-22 15:03:03 +00:00
mask={getMask(country.locale)}
withBorder={false}
2022-09-27 05:26:10 +00:00
tabIndex={1}
2022-09-22 15:03:03 +00:00
value={country.dialCode}
onChange={handleChange}
/>
<StyledDropDown
open={isOpen}
clickOutsideAction={() => setIsOpen(!isOpen)}
isDefaultMode={false}
manualWidth="100%"
>
<InputBlock
type="text"
iconName="static/images/search.react.svg"
2022-09-29 12:37:33 +00:00
placeholder={props.searchPlaceholderText}
2022-09-22 15:03:03 +00:00
value={searchValue}
2022-09-27 05:26:10 +00:00
tabIndex={2}
2022-09-22 15:03:03 +00:00
scale={true}
2022-09-28 14:18:07 +00:00
onChange={handleSearch}
2022-09-22 15:03:03 +00:00
style={{ marginBottom: "6px" }}
/>
<Box>
{filteredOptions.length ? (
<List
itemData={filteredOptions}
height={108}
itemCount={filteredOptions.length}
itemSize={36}
outerElementType={CustomScrollbarsVirtualList}
width="auto"
>
{Row}
</List>
) : (
2022-09-29 12:37:33 +00:00
<StyledText>{props.searchEmptyMessage}</StyledText>
2022-09-22 15:03:03 +00:00
)}
</Box>
</StyledDropDown>
</StyledBox>
2022-09-29 12:37:33 +00:00
{!isValid && <ErrorText>{props.errorMessage}</ErrorText>}
2022-09-22 15:03:03 +00:00
</>
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";