1
- import type { TemplateOnlyComponent } from ' @ember/component/template-only' ;
2
1
import { action } from ' @ember/object' ;
3
2
import Component from ' @glimmer/component' ;
4
3
import { tracked } from ' @glimmer/tracking' ;
5
- import { type TCountryCode , countries , getEmojiFlag } from ' countries-list' ;
6
4
import {
7
- type CountryCallingCode ,
8
- type CountryCode ,
9
- getCountries ,
10
- getCountryCallingCode ,
11
- getExampleNumber ,
12
- isValidPhoneNumber ,
13
- } from ' libphonenumber-js' ;
14
- // @ts-expect-error import not found
15
- import examples from ' libphonenumber-js/mobile/examples' ;
5
+ getCountryCodeForRegionCode ,
6
+ getExample ,
7
+ getSupportedRegionCodes ,
8
+ parsePhoneNumber ,
9
+ } from ' awesome-phonenumber' ;
10
+ import { type TCountryCode , countries , getEmojiFlag } from ' countries-list' ;
16
11
import { debounce } from ' lodash' ;
17
12
18
13
import { type InputValidationState } from ' ../input/index.gts' ;
@@ -30,19 +25,20 @@ interface Signature {
30
25
}
31
26
32
27
interface CountryInfo {
33
- callingCode? : CountryCallingCode ;
34
- code: CountryCode ;
28
+ callingCode? : string ;
29
+ code: string ;
35
30
example? : {
36
- callingCode: CountryCallingCode ;
31
+ callingCode: string ;
37
32
nationalNumber: string ;
38
33
};
39
34
flag? : string ;
40
35
name? : string ;
41
36
}
42
37
43
- const getCountryInfo = (countryCode : CountryCode ): CountryInfo | undefined => {
44
- let example = getExampleNumber (countryCode , examples );
45
- let callingCode = getCountryCallingCode (countryCode );
38
+ const getCountryInfo = (countryCode : string ): CountryInfo | undefined => {
39
+ let example = getExample (countryCode );
40
+ let callingCode = getCountryCodeForRegionCode (countryCode );
41
+
46
42
let c = countries [countryCode as TCountryCode ];
47
43
if (c === undefined ) {
48
44
// here some country code may not be found due to the discrepancy between countries-list and libphonenumber-js library
@@ -52,13 +48,13 @@ const getCountryInfo = (countryCode: CountryCode): CountryInfo | undefined => {
52
48
}
53
49
return {
54
50
code: countryCode ,
55
- callingCode ,
51
+ callingCode: callingCode . toString () ,
56
52
name: c ? c .name : undefined ,
57
53
flag: getEmojiFlag (countryCode as TCountryCode ),
58
54
example: example
59
55
? {
60
- callingCode ,
61
- nationalNumber: example .format ( ' NATIONAL ' ) ,
56
+ callingCode: callingCode . toString () ,
57
+ nationalNumber: example .number ?. international ?? ' ' ,
62
58
}
63
59
: undefined ,
64
60
};
@@ -73,18 +69,16 @@ class PhoneInput extends Component<Signature> {
73
69
@action onSelectItem(item : CountryInfo ): void {
74
70
this .selectedItem = item ;
75
71
if (this .input .length > 0 ) {
76
- this .validationState = isValidPhoneNumber (
77
- this .input ,
78
- this .selectedItem .code ,
79
- )
80
- ? ' valid'
81
- : ' invalid' ;
72
+ const parsedPhoneNumber = parsePhoneNumber (this .input , {
73
+ regionCode: this .selectedItem .code ,
74
+ });
75
+ this .validationState = parsedPhoneNumber .valid ? ' valid' : ' invalid' ;
82
76
}
83
77
}
84
78
85
79
constructor (owner : unknown , args : any ) {
86
80
super (owner , args );
87
- this .items = getCountries ()
81
+ this .items = getSupportedRegionCodes ()
88
82
.map ((code ) => {
89
83
return getCountryInfo (code );
90
84
})
@@ -107,10 +101,17 @@ class PhoneInput extends Component<Signature> {
107
101
}
108
102
109
103
private debouncedInput = debounce ((input : string ) => {
110
- this .validationState = isValidPhoneNumber (input , this .selectedItem .code )
111
- ? ' valid'
112
- : ' invalid' ;
113
104
this .input = input ;
105
+
106
+ if (input === ' ' ) {
107
+ this .validationState = ' initial' ;
108
+ return ;
109
+ }
110
+
111
+ const parsedPhoneNumber = parsePhoneNumber (input , {
112
+ regionCode: this .selectedItem .code ,
113
+ });
114
+ this .validationState = parsedPhoneNumber .valid ? ' valid' : ' invalid' ;
114
115
// save when the state is valid
115
116
if (this .validationState === ' valid' ) {
116
117
this .args .onInput (this .input );
@@ -151,13 +152,13 @@ export interface SelectedItemSignature {
151
152
Element: HTMLDivElement ;
152
153
}
153
154
154
- const PhoneSelectedItem: TemplateOnlyComponent <SelectedItemSignature > =
155
- // eslint-disable-next-line prettier/prettier TODO: fix this eslint error --> Insert `·[` prettier/prettier
155
+ class PhoneSelectedItem extends Component <SelectedItemSignature > {
156
156
<template >
157
157
<div >
158
158
{{@ option.flag }}
159
159
+{{@ option.callingCode }}
160
160
</div >
161
- </template >;
161
+ </template >
162
+ }
162
163
163
164
export default PhoneInput ;
0 commit comments