'Can I create a mask for an antd-country-phone-input?

I am using the antd-country-phone-input in my form for international phone numbers. However this does not have a mask and I want to have a masked input. I have searched for hours for a solution to this, but have not come up with any workable solution. Any ideas how to add a mask to this input? Code

//library 
import CountryPhoneInput, {
    ConfigProvider,
    CountryPhoneInputValue,
} from "antd-country-phone-input";

//returning
<ConfigProvider
            locale={en}
            areaMapper={(area) => {
                return {
                    ...area,
                    emoji: (
                        <img
                            alt="flag"
                            style={{ width: 18, height: 18, verticalAlign: "sub" }}
                            src={getFlag(area.short)}
                        />
                    ),
                };
            }}
        >
            <CountryPhoneInput
                id={id}
                value={{
                    code: countryValue.code,
                    short: countryValue.short,
                    phone: countryValue.phone,
                }}
                onChange={(value) => {
                    if (value.code !== Number(countryValue.code)) {
                        setCountryValue({
                            code: value.code,
                            short: value.short,
                            phone: value.phone,
                        });
                    }
                    // onChange("+" + value.code!.toString() + phone);
                }}
                onBlur={() => setValidNumber(isValidPhoneNumber(value))}
                style={{ height: "50px" }}
                className="phone-height"
                autoComplete="none"
                placeholder={mask}
            ></CountryPhoneInput>
        </ConfigProvider>


Solution 1:[1]

This is what i put together in the end to come up with a masked input for international phone numbers. It works for most countries phone numbers

const PhoneMaskWidget = (props: any) => {
    const  {value, onChange, id} = props;
    const [countryValue, setCountryValue] = useState<CountryPhoneInputValue>({
        short: "US",
        code: 1,
        phone: "",
    });
    const [mask, setMask] = useState<string>("(XXX)XXX-XXXX");
    const [mounting, setMounting] = useState<boolean>(true);
    const [validNumber, setValidNumber] = useState<boolean>(true);
    const [countrySwitched, setCountrySwtiched] = useState<boolean>(false);

    const stripPhone = (phone: any) => {
        let formattedPhone = phone.replace(/[()\-. ]/g, "");
        return formattedPhone;
    };

    const getMask = (mask: any) => {
        mask = Array.isArray(mask) ? mask[1].split("#").join("X") : mask.split("#").join("X");
        const firstIndex = mask.search(/\d/); // will give you the first digit in the string
        let lastIndex = -1;
        if (firstIndex > -1) {
            for (let i = firstIndex + 1; i < mask.length; i++) {
                const element = mask[i];
                if (!Number(element)) {
                    lastIndex = i - 1;
                    break;
                }
            }

            let remove = "";
            if (mask[firstIndex - 1] === "(" && mask[lastIndex + 1] === ")") {
                remove = mask.slice(firstIndex - 1, lastIndex + 2);
                mask = mask.replace(remove, "");
                setMask(mask);
            }
        }
        return mask;
    };

    const getFlag = (short: string) => {
        const data = require(`world_countries_lists/flags/24x24/${short.toLowerCase()}.png`);
        // for dumi
        if (typeof data === "string") {
            return data;
        }
        // for CRA
        return data.default;
    };

    const maskInput = useCallback(
        (phoneValue: string, masking?: string) => {
            masking = masking || mask;
            let phone = stripPhone(phoneValue);
            const phoneLength = stripPhone(masking).length;
            if (phone.length > phoneLength) {
                phone = phone.substring(0, phoneLength);
                setCountryValue({ ...countryValue, phone: phone });
            }
            let maskedPhone = "";
            let brackets = -1;
            let dash = -1;
            let secondDash = -1;
            if (masking.indexOf("(") > -1) {
                const open = masking.indexOf("(");
                const close = masking.indexOf(")");
                brackets = close - (open + 1);
            }
            if (masking.indexOf("-") > -1) {
                dash = masking.indexOf("-");
            }
            if (masking.lastIndexOf("-") > -1) {
                secondDash = masking.lastIndexOf("-");
            }
            if (brackets > -1) {
                if (phone!.length > dash - 2) {
                    maskedPhone =
                        "(" +
                        phone?.substring(0, brackets) +
                        ") " +
                        phone?.substring(brackets, dash - 2) +
                        "-" +
                        phone.substring(6, phone.length);
                } else if (phone!.length > brackets && brackets >= 0) {
                    maskedPhone =
                        "(" +
                        phone?.substring(0, brackets) +
                        ") " +
                        phone.substring(brackets, phone.length);
                } else {
                    maskedPhone = phone;
                }
            } else {
                if (phone.length > secondDash - 1 && secondDash > -1 && secondDash !== dash) {
                    maskedPhone =
                        phone.substring(0, dash) +
                        "-" +
                        phone.substring(dash, secondDash - 1) +
                        "-" +
                        phone.substring(secondDash - 1, phone.length);
                } else if (phone.length > dash && dash > -1) {
                    maskedPhone =
                        phone.substring(0, dash) + "-" + phone.substring(dash, phone.length);
                } else {
                    maskedPhone = phone;
                }
            }
            return maskedPhone;
        },
        [mask]
    );

    const parsePhoneNumber = useCallback(
        (value: string) => {
            if (!value) return;
            let phone = phoneparser.parse(value);
            const number = phone?.localized?.stripped || phone.stripped;
            const countryShort = phone?.country?.iso3166?.alpha2;
            if (!countryShort) {
                return;
            }
            const country = countries.find((c: any) => c.iso === countryShort);
            const mask = getMask(country.mask);
            setMask(mask);
            if (countryShort && number && country.code) {
                setCountryValue({
                    short: countryShort,
                    code: country.code,
                    phone: maskInput(number.slice(-stripPhone(mask).length), mask),
                });
            }
        },
        [maskInput]
    );

    useEffect(() => {
        if (!countryValue) return;
        if (!mounting) {
            const country = countries.find((c: any) => c.iso === countryValue.short);
            setMask(getMask(country.mask));
            setCountryValue({
                ...countryValue,
                phone: countrySwitched ? "" : countryValue.phone,
            });
            setCountrySwtiched(false);
        }
        if (mounting) {
            if (value) parsePhoneNumber(value);
            setMounting(false);
        }
    }, [countryValue.short, countrySwitched, mounting, value, parsePhoneNumber]);

    return (
        <ConfigProvider
            locale={en}
            areaMapper={(area) => {
                return {
                    ...area,
                    emoji: (
                        <img
                            alt="flag"
                            style={{ width: 18, height: 18, verticalAlign: "sub" }}
                            src={getFlag(area.short)}
                        />
                    ),
                };
            }}
        >
            <CountryPhoneInput
                id={id}
                value={{
                    code: countryValue.code,
                    short: countryValue.short,
                    phone: !value || value === "" ? "" : countryValue.phone,
                }}
                onChange={(value) => {
                    if (value.short !== countryValue.short) {
                        setCountrySwtiched(true);
                    }
                    const maskedPhone = maskInput(value.phone ? value.phone : "");

                    setCountryValue({
                        code: value.code,
                        short: value.short,
                        phone: maskedPhone,
                    });
                    onChange("+" + value.code!.toString() + " " + maskedPhone);
                    // onChange("+" + value.code!.toString() + stripPhone(maskedPhone));
                }}
                onBlur={() => {
                    const maskedPhone = maskInput(countryValue.phone!);
                    setValidNumber(
                        isValidPhoneNumber("+ " + countryValue.code + stripPhone(maskedPhone))
                    );
                }}
                style={{ height: "50px" }}
                className="phone-height"
                autoComplete="none"
                placeholder={mask}
            ></CountryPhoneInput>
        </ConfigProvider>
    );
};

export default PhoneMaskWidget;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 L. Wolf