"use client"; import { useEffect, useRef, useState } from "react"; import { IMaskInput } from "react-imask"; import { InputBase, type InputBaseProps, type PolymorphicComponentProps, } from "@mantine/core"; import { useUncontrolled } from "@mantine/hooks"; import CountrySelect from "@/components/PhoneInput/components/CountrySelect"; import getFormat from "@/components/PhoneInput/utils/getFormat"; import getInitialDataFromValue from "@/components/PhoneInput/utils/getInitialDataFromValue"; export type Props = { initialCountryCode?: string; defaultValue?: string; } & Omit< PolymorphicComponentProps, "onChange" | "defaultValue" > & { onChange: (value: string | null) => void }; const PhoneInput = ({ initialCountryCode = "RU", value: _value, onChange: _onChange, defaultValue, ...props }: Props) => { const [value, onChange] = useUncontrolled({ value: _value, defaultValue, onChange: _onChange, }); const initialData = useRef( getInitialDataFromValue(value, initialCountryCode) ); const [country, setCountry] = useState(initialData.current.country); const [format, setFormat] = useState(initialData.current.format); const [localValue, setLocalValue] = useState( initialData.current.localValue ); const inputRef = useRef(null); const lastNotifiedValue = useRef(value ?? ""); useEffect(() => { const value = localValue.trim(); if (value !== lastNotifiedValue.current) { lastNotifiedValue.current = value; onChange(value); } }, [country.code, localValue]); useEffect(() => { if ( typeof value !== "undefined" && value !== lastNotifiedValue.current ) { const initialData = getInitialDataFromValue( value, initialCountryCode ); lastNotifiedValue.current = value; setCountry(initialData.country); setFormat(initialData.format); setLocalValue(initialData.localValue); } }, [value]); const { readOnly, disabled } = props; const leftSectionWidth = 90; return ( { setCountry(country); setFormat(getFormat(country.code)); setLocalValue(""); if (inputRef.current) { inputRef.current.focus(); } }} leftSectionWidth={leftSectionWidth} /> } leftSectionWidth={leftSectionWidth} styles={{ input: { fontSize: 17, paddingLeft: `calc(${leftSectionWidth}px + var(--mantine-spacing-sm))`, }, section: { borderRight: "1px solid var(--mantine-color-default-border)", }, }} inputMode={"numeric"} mask={format.mask} value={localValue} onAccept={value => setLocalValue(value)} /> ); }; export default PhoneInput;