@blocklet/payment-react
Version:
Reusable react components for payment kit v2
93 lines (92 loc) • 3.02 kB
JavaScript
import { jsx } from "react/jsx-runtime";
import { InputAdornment } from "@mui/material";
import omit from "lodash/omit";
import { useEffect, useRef, useCallback } from "react";
import { useFormContext, useWatch } from "react-hook-form";
import { defaultCountries, usePhoneInput } from "react-international-phone";
import { useMount } from "ahooks";
import FormInput from "../../components/input.js";
import { isValidCountry } from "../../libs/util.js";
import CountrySelect from "../../components/country-select.js";
import { getPhoneUtil } from "../../libs/phone-validator.js";
export default function PhoneInput({ ...props }) {
const countryFieldName = props.countryFieldName || "billing_address.country";
const { control, getValues, setValue, trigger } = useFormContext();
const values = getValues();
const isUpdatingRef = useRef(false);
const safeUpdate = useCallback((callback) => {
if (isUpdatingRef.current) return;
try {
isUpdatingRef.current = true;
callback();
} finally {
requestAnimationFrame(() => {
isUpdatingRef.current = false;
});
}
}, []);
const { phone, handlePhoneValueChange, inputRef, country, setCountry } = usePhoneInput({
defaultCountry: isValidCountry(values[countryFieldName]) ? values[countryFieldName] : "us",
value: values[props.name] || "",
countries: defaultCountries,
onChange: (data) => {
safeUpdate(() => {
setValue(props.name, data.phone);
setValue(countryFieldName, data.country);
});
}
});
const userCountry = useWatch({ control, name: countryFieldName });
useEffect(() => {
if (!userCountry || userCountry === country) return;
safeUpdate(() => {
setCountry(userCountry);
});
}, [userCountry, country, setCountry, safeUpdate]);
useMount(() => {
getPhoneUtil().catch((err) => {
console.error("Failed to preload phone validator:", err);
});
});
const onCountryChange = useCallback(
(v) => {
safeUpdate(() => {
setCountry(v);
});
},
[setCountry, safeUpdate]
);
const handleBlur = useCallback(() => {
trigger(props.name);
}, [props.name]);
return (
// @ts-ignore
/* @__PURE__ */ jsx(
FormInput,
{
value: phone,
onChange: handlePhoneValueChange,
type: "tel",
inputRef,
onBlur: handleBlur,
InputProps: {
startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", style: { marginRight: "2px", marginLeft: "-8px" }, children: /* @__PURE__ */ jsx(
CountrySelect,
{
value: country,
onChange: onCountryChange,
name: countryFieldName,
sx: {
"&.MuiOutlinedInput-notchedOutline": {
borderColor: "transparent !important"
}
},
showDialCode: true
}
) })
},
...omit(props, ["countryFieldName"])
}
)
);
}