import parsePhoneNumberFromString , { AsYouType , CountryCode , formatIncompletePhoneNumber , getCountryCallingCode , getExampleNumber , } from 'libphonenumber-js/min' ; import metadata from 'libphonenumber-js/metadata.min.json' ; import examples from 'libphonenumber-js/examples.mobile.json' ; import isTruthy from '@proton/shared/lib/helpers/isTruthy' ; import { getFlagSvg } from './flagSvgs' ; import { callingCodeToLeading , countries } from './data' ; export const getTrimmedString = ( string ) => { const slicedValue = string . match ( /\([\d]+$/ ) ? string . slice ( 0 , - 1 ) : string ; const trimmedString = slicedValue . replace ( /[^0-9+]+/g , '' ) ; if ( ! trimmedString . length ) { return '' ; } return trimmedString [ 0 ] + trimmedString . slice ( 1 ) . replace ( /\+/g , '' ) ; } ; export const getSafeCountryCallingCode = ( country ) => { try { return getCountryCallingCode ( country as CountryCode ) as string ; } catch ( e ) { return '' ; } } ; export const getCountryFromCallingCode = ( callingCode ) => { const countries = metadata . country_calling_codes [ callingCode ] ; if ( ! countries || countries . length === 0 ) { return ; } if ( countries . length === 1 ) { return countries [ 0 ] ; } return countries [ 0 ] ; } ; export const getNumberWithCountryCode = ( value , countryCallingCode ) => { if ( value . includes ( '+' ) ) { return value ; } if ( ! countryCallingCode ) { return value ; } return `+${ countryCallingCode }${ value }` ; } ; export const getExamplePlaceholder = ( country ) => { const example = getExampleNumber ( country as CountryCode , examples ) ; if ( ! example ) { return '' ; } return example . formatInternational ( ) ; } ; export const getNumberWithoutCountryCode = ( value , countryCallingCode ) => { return value . replace ( `+${ countryCallingCode }` , '' ) . trim ( ) ; } ; export const getCountryFromNumber = ( value ) => { const asYouType = new AsYouType ( ) ; asYouType . input ( value ) ; const result = asYouType . getNumber ( ) ; if ( result ) { return result . country || getCountryFromCallingCode ( result . countryCallingCode as string ) || '' ; } const country = asYouType . getCountry ?. ( ) as CountryCode ; if ( country ) { return country ; } if ( ! value . length ) { return '' ; } if ( value [ 0 ] === '+' ) { const callingCode = value . slice ( 1 ) ; const country = getCountryFromCallingCode ( callingCode ) ; return country || '' ; } return '' ; } ; export interface CountryOptionData { countryCode : string ; countryName : string ; countryCallingCode : string ; countryFlag : string ; } export const getCountries = ( ) : CountryOptionData [ ] => { return Object . keys ( metadata . countries ) . map ( ( countryCode ) : CountryOptionData | undefined => { const countryCallingCode = getSafeCountryCallingCode ( countryCode as CountryCode ) ; const countryName = countries [ countryCode ] ; const countryFlag = getFlagSvg ( countryCode ) ; if ( ! countryFlag || ! countryName || ! countryCallingCode ) { return ; } return { countryCode , countryName , countryCallingCode , countryFlag , } ; } ) . filter ( isTruthy ) . sort ( ( a , b ) => a . countryName . localeCompare ( b . countryName ) ) ; } ; export const getCursorPosition = ( digitIndex , value ) => { const regex = /[\d+]/ ; let n = 0 ; let i = 0 ; for ( ; i < value . length ; ++ i ) { if ( value [ i ] . match ( regex ) ) { if ( n ++ >= digitIndex ) { break ; } } } if ( ! value [ i - 1 ] ?. match ( regex ) ) { i -= 1 ; } return Math . max ( 0 , Math . min ( i , value . length ) ) ; } ; export const getFormattedValue = ( number ) => { const result = parsePhoneNumberFromString ( number ) ; if ( result && result . isValid ( ) ) { return result . formatInternational ( ) ; } return formatIncompletePhoneNumber ( number ) ; } ; export const getSpecificCountry = ( value , countryCallingCode , countryCode ) : [ string , number ] => { const leadings = callingCodeToLeading [ countryCallingCode ] ; if ( ! leadings ) { return [ countryCode , 0 ] ; } return leadings . reduce ( ( acc , { countryCode , areaCodes } ) => { const result = areaCodes . find ( ( areaCode ) => value . startsWith ( areaCode ) ) ; if ( result && result . length >= acc [ 1 ] ) { return [ countryCode , result . length ] ; } return acc ; } , [ countryCode , 0 ] ) ; } ; export const getSpecificMaxLength = ( countryCallingCode , countryCode ) => { const leadings = callingCodeToLeading [ countryCallingCode ] || [ ] ; const areaCodes = leadings . find ( ( leading ) => { return countryCode === leading . countryCode ; } ) ?. areaCodes || [ ] ; return areaCodes . reduce ( ( acc , cur ) => { return Math . max ( acc , cur . length ) ; } , 0 ) ; } ;