text: import { useRef, useState, useCallback, useEffect } from 'react'
  import { AsYouType, getCountryCallingCode, parseDigits } from 'libphonenumber-js/core'
  
  import getInternationalPhoneNumberPrefix from './helpers/getInternationalPhoneNumberPrefix'
  
  /**
   * Returns `[phoneDigits, setPhoneDigits]`.
   * "Phone digits" includes not only "digits" but also a `+` sign.
   */
  export default function usePhoneDigits({
  	value,
  	onChange,
  	country,
  	defaultCountry,
  	international,
  	withCountryCallingCode,
  	useNationalFormatForDefaultCountryValue,
  	metadata
  }) {
  	const countryMismatchDetected = useRef()
  	const onCountryMismatch = (value, country, actualCountry) => {
  		console.error(`[react-phone-number-input] Expected phone number ${value} to correspond to country ${country} but ${actualCountry ? 'in reality it corresponds to country ' + actualCountry : 'it doesn\'t'}.`)
  		countryMismatchDetected.current = true
  	}
  	const getInitialPhoneDigits = () => getPhoneDigitsForValue(
  		value,
  		country,
  		international,
  		withCountryCallingCode,
  		defaultCountry,
  		useNationalFormatForDefaultCountryValue,
  		metadata,
  		onCountryMismatch
  	)
  	// This is only used to detect `country` property change.
  	const [prevCountry, setPrevCountry] = useState(country)
  	// This is only used to detect `defaultCountry` property change.
  	const [prevDefaultCountry, setPrevDefaultCountry] = useState(defaultCountry)
  	// `phoneDigits` is the `value` passed to the `<input/>`.
  	const [phoneDigits, setPhoneDigits] = useState(getInitialPhoneDigits())
  	// This is only used to detect `value` property changes.
  	const [valueForPhoneDigits, setValueForPhoneDigits] = useState(value)
  	// Rerender hack.
  	const [rerenderTrigger, setRerenderTrigger] = useState()
  	const rerender = useCallback(() => setRerenderTrigger({}), [setRerenderTrigger])
  	// If `value` property has been changed externally
  	// then re-initialize the component.
  	useEffect(() => {
  		if (value !== valueForPhoneDigits) {
  			setValueForPhoneDigits(value)
  			setPhoneDigits(getInitialPhoneDigits())
  		}
  	}, [value])
  	// If the `country` has been changed then re-initialize the component.
  	useEffect(() => {
  		if (country !== prevCountry) {
  			setPrevCountry(country)
  			setPhoneDigits(getInitialPhoneDigits())
  		}
  	}, [country])
  	// If the `defaultCountry` has been changed then re-initialize the component.
  	useEffect(() => {
  		if (defaultCountry !== prevDefaultCountry) {
  			setPrevDefaultCountry(defaultCountry)
  			setPhoneDigits(getInitialPhoneDigits())
  		}
  	}, [defaultCountry])
  	// Update the `value` after `valueForPhoneDigits` has been updated.
  	useEffect(() => {
  		if (valueForPhoneDigits !== value) {
  			onChange(valueForPhoneDigits)
  		}
  	}, [valueForPhoneDigits])
  	const onSetPhoneDigits = useCallback((phoneDigits) => {
  		let value
  		if (country) {
  			if (international && withCountryCallingCode) {
  				// The `<input/>` value must start with the country calling code.
  				const prefix = getInternationalPhoneNumberPrefix(country, metadata)
  				if (phoneDigits.indexOf(prefix) !== 0) {
  					// If a user tabs into a phone number input field
  					// that is `international` and `withCountryCallingCode`,
  					// and then starts inputting local phone number digits,
  					// the first digit would get "swallowed" if the fix below wasn't implemented.
  					// https://gitlab.com/catamphetamine/react-phone-number-input/-/issues/43
  					if (phoneDigits && phoneDigits[0] !== '+') {
  						phoneDigits = prefix + phoneDigits
  					} else {
  						// // Reset phone digits if they don't start with the correct prefix.
  						// // Undo the `<input/>` value change if it doesn't.
  						if (countryMismatchDetected.current) {
  							// In case of a `country`/`value` mismatch,
  							// if it performed an "undo" here, then
  							// it wouldn't let a user edit their phone number at all,
  							// so this special case at least allows phone number editing
  							// when `value` already doesn't match the `country`.
  						} else {
  							// If it simply did `phoneDigits = prefix` here,
  							// then it could have no effect when erasing phone number
  							// via Backspace, because `phoneDigits` in `state` wouldn't change
  							// as a result, because it was `prefix` and it became `prefix`,
  							// so the component wouldn't rerender, and the user would be able
  							// to erase the country calling code part, and that part is
  							// assumed to be non-eraseable. That's why the component is
  							// forcefully rerendered here.
  							setPhoneDigits(prefix)
  							setValueForPhoneDigits(undefined)
  							// Force a re-render of the `<input/>` with previous `phoneDigits` value.
  							return rerender()
  						}
  					}
  				}
  			} else {
  				// Entering phone number either in "national" format
  				// when `country` has been specified, or in "international" format
  				// when `country` has been specified but `withCountryCallingCode` hasn't.
  				// Therefore, `+` is not allowed.
  				if (phoneDigits && phoneDigits[0] === '+') {
  					// Remove the `+`.
  					phoneDigits = phoneDigits.slice(1)
  				}
  			}
  		} else if (!defaultCountry) {
  			// Force a `+` in the beginning of a `value`
  			// when no `country` and `defaultCountry` have been specified.
  			if (phoneDigits && phoneDigits[0] !== '+') {
  				// Prepend a `+`.
  				phoneDigits = '+' + phoneDigits
  			}
  		}
  		// Convert `phoneDigits` to `value`.
  		if (phoneDigits) {
  			const asYouType = new AsYouType(country || defaultCountry, metadata)
  			asYouType.input(
  				country && international && !withCountryCallingCode ?
  				`+${getCountryCallingCode(country, metadata)}${phoneDigits}` :
  				phoneDigits
  			)
  			const phoneNumber = asYouType.getNumber()
  			// If it's a "possible" incomplete phone number.
  			if (phoneNumber) {
  				value = phoneNumber.number
  			}
  		}
  		setPhoneDigits(phoneDigits)
  		setValueForPhoneDigits(value)
  	}, [
  		country,
  		international,
  		withCountryCallingCode,
  		defaultCountry,
  		metadata,
  		setPhoneDigits,
  		setValueForPhoneDigits,
  		rerender,
  		countryMismatchDetected
  	])
  	return [
  		phoneDigits,
  		onSetPhoneDigits
  	]
  }
  
  /**
   * Returns phone number input field value for a E.164 phone number `value`.
   * @param  {string} [value]
   * @param  {string} [country]
   * @param  {boolean} [international]
   * @param  {boolean} [withCountryCallingCode]
   * @param  {string} [defaultCountry]
   * @param  {boolean} [useNationalFormatForDefaultCountryValue]
   * @param  {object} metadata
   * @return {string}
   */
  function getPhoneDigitsForValue(
  	value,
  	country,
  	international,
  	withCountryCallingCode,
  	defaultCountry,
  	useNationalFormatForDefaultCountryValue,
  	metadata,
  	onCountryMismatch
  ) {
  	if (country && international && withCountryCallingCode) {
  		const prefix = getInternationalPhoneNumberPrefix(country, metadata)
  		if (value) {
  			if (value.indexOf(prefix) !== 0) {
  				onCountryMismatch(value, country)
  			}
  			return value
  		}
  		return prefix
  	}
  	if (!value) {
  		return ''
  	}
  	if (!country && !defaultCountry) {
  		return value
  	}
  	const asYouType = new AsYouType(undefined, metadata)
  	asYouType.input(value)
  	const phoneNumber = asYouType.getNumber()
  	if (phoneNumber) {
  		if (country) {
  			if (phoneNumber.country && phoneNumber.country !== country) {
  				onCountryMismatch(value, country, phoneNumber.country)
  			} else if (phoneNumber.countryCallingCode !== getCountryCallingCode(country, metadata)) {
  				onCountryMismatch(value, country)
  			}
  			if (international) {
  				return phoneNumber.nationalNumber
  			}
  			return parseDigits(phoneNumber.formatNational())
  		} else {
  			// `phoneNumber.countryCallingCode` is compared here  instead of
  			// `phoneNumber.country`, because, for example, a person could have
  			// previously input a phone number (in "national" format) that isn't
  			// 100% valid for the `defaultCountry`, and if `phoneNumber.country`
  			// was compared, then it wouldn't match, and such phone number
  			// wouldn't be formatted as a "national" one, and instead would be
  			// formatted as an "international" one, confusing the user.
  			// Comparing `phoneNumber.countryCallingCode` works around such issues.
  			//
  			// Example: `defaultCountry="US"` and the `<input/>` is empty.
  			// The user inputs: "222 333 4444", which gets formatted to "(222) 333-4444".
  			// The user then clicks "Save", the page is refreshed, and the user sees
  			// that the `<input/>` value is now "+1 222 333 4444" which confuses the user:
  			// the user expected the `<input/>` value to be "(222) 333-4444", same as it
  			// was when they've just typed it in. The cause of the issue is that "222 333 4444"
  			// is not a valid national number for US, and `phoneNumber.country` is compared
  			// instead of `phoneNumber.countryCallingCode`. After the `phoneNumber.country`
  			// comparison is replaced with `phoneNumber.countryCallingCode` one, the issue
  			// is no longer the case.
  			//
  			if (phoneNumber.countryCallingCode && phoneNumber.countryCallingCode === getCountryCallingCode(defaultCountry, metadata) && useNationalFormatForDefaultCountryValue) {
  				return parseDigits(phoneNumber.formatNational())
  			}
  			return value
  		}
  	} else {
  		return ''
  	}
  }