@blocklet/payment-react
Version:
Reusable react components for payment kit v2
97 lines (96 loc) • 3.12 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import { useEffect, useRef, useCallback } from "react";
import { Box, InputBase, InputAdornment, Typography } from "@mui/material";
import { defaultCountries, usePhoneInput } from "react-international-phone";
import { useMount } from "ahooks";
import CountrySelect from "./country-select.js";
import { isValidCountry } from "../libs/util.js";
import { getPhoneUtil } from "../libs/phone-validator.js";
export default function PhoneField({
value,
country: externalCountry,
onChange,
onCountryChange,
label,
error = void 0,
onBlur = void 0
}) {
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(externalCountry) ? externalCountry : "us",
value: value || "",
countries: defaultCountries,
onChange: (data) => {
safeUpdate(() => {
onChange(data.phone);
onCountryChange(data.country);
});
}
});
useMount(() => {
getPhoneUtil().catch((err) => {
console.error("Failed to preload phone validator:", err);
});
});
useEffect(() => {
if (!externalCountry || externalCountry === country) return;
safeUpdate(() => {
setCountry(externalCountry);
});
}, [externalCountry, country, setCountry, safeUpdate]);
const handleCountryChange = useCallback(
(v) => {
safeUpdate(() => {
setCountry(v);
onCountryChange(v);
});
},
[setCountry, safeUpdate, onCountryChange]
);
return /* @__PURE__ */ jsxs(Box, { sx: { mb: 1.5 }, children: [
/* @__PURE__ */ jsx(Typography, { sx: { fontSize: 13, fontWeight: 600, color: "text.primary", mb: 0.5 }, children: label }),
/* @__PURE__ */ jsx(
InputBase,
{
fullWidth: true,
value: phone,
onChange: handlePhoneValueChange,
onBlur,
type: "tel",
inputRef,
startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", sx: { mr: 0.25, ml: -0.5 }, children: /* @__PURE__ */ jsx(
CountrySelect,
{
value: country,
onChange: handleCountryChange,
sx: {
".MuiOutlinedInput-notchedOutline": { borderColor: "transparent !important" },
"& .MuiSelect-select": { py: 0, pr: "20px !important" }
},
showDialCode: true
}
) }),
sx: {
bgcolor: (theme) => theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "grey.50",
borderRadius: "8px",
px: 1.5,
py: 0.75,
fontSize: 14,
"& .MuiInputBase-input": { p: 0 }
}
}
),
error && /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 12, color: "error.main", mt: 0.25 }, children: error })
] });
}