@transferwise/components 46.5.0 → 46.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/i18n/th.json +3 -3
- package/build/index.esm.js +252 -464
- package/build/index.esm.js.map +1 -1
- package/build/index.js +253 -465
- package/build/index.js.map +1 -1
- package/build/main.css +6 -17
- package/build/styles/inputs/Input.css +0 -4
- package/build/styles/inputs/SelectInput.css +6 -1
- package/build/styles/inputs/TextArea.css +0 -4
- package/build/styles/main.css +6 -17
- package/build/styles/select/Select.css +0 -4
- package/build/types/common/locale/index.d.ts +26 -43
- package/build/types/common/locale/index.d.ts.map +1 -1
- package/build/types/common/textFormat/formatWithPattern/formatWithPattern.d.ts +1 -1
- package/build/types/common/textFormat/formatWithPattern/formatWithPattern.d.ts.map +1 -1
- package/build/types/common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.d.ts +2 -2
- package/build/types/common/textFormat/getCursorPositionAfterKeystroke/getCursorPositionAfterKeystroke.d.ts.map +1 -1
- package/build/types/common/textFormat/getSymbolsInPatternWithPosition/getSymbolsInPatternWithPosition.d.ts +5 -1
- package/build/types/common/textFormat/getSymbolsInPatternWithPosition/getSymbolsInPatternWithPosition.d.ts.map +1 -1
- package/build/types/common/textFormat/unformatWithPattern/unformatWithPattern.d.ts +1 -1
- package/build/types/common/textFormat/unformatWithPattern/unformatWithPattern.d.ts.map +1 -1
- package/build/types/index.d.ts +3 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts +7 -11
- package/build/types/inputWithDisplayFormat/InputWithDisplayFormat.d.ts.map +1 -1
- package/build/types/inputWithDisplayFormat/index.d.ts +2 -1
- package/build/types/inputWithDisplayFormat/index.d.ts.map +1 -1
- package/build/types/inputs/SelectInput.d.ts +6 -5
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts +22 -27
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/data/countries.d.ts +5 -10
- package/build/types/phoneNumberInput/data/countries.d.ts.map +1 -1
- package/build/types/phoneNumberInput/index.d.ts +1 -1
- package/build/types/phoneNumberInput/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts +8 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts +8 -4
- package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts +2 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/index.d.ts +11 -13
- package/build/types/phoneNumberInput/utils/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts +6 -1
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts +2 -1
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts +7 -1
- package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts +1 -1
- package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts.map +1 -1
- package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts +7 -11
- package/build/types/textareaWithDisplayFormat/TextareaWithDisplayFormat.d.ts.map +1 -1
- package/build/types/textareaWithDisplayFormat/index.d.ts +2 -1
- package/build/types/textareaWithDisplayFormat/index.d.ts.map +1 -1
- package/build/types/withDisplayFormat/WithDisplayFormat.d.ts +55 -83
- package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
- package/build/types/withDisplayFormat/index.d.ts +2 -1
- package/build/types/withDisplayFormat/index.d.ts.map +1 -1
- package/package.json +3 -4
- package/src/common/locale/{index.spec.js → index.spec.ts} +4 -4
- package/src/common/locale/index.ts +96 -0
- package/src/common/textFormat/formatWithPattern/{formatWithPattern.js → formatWithPattern.ts} +8 -4
- package/src/common/textFormat/getCursorPositionAfterKeystroke/{getCursorPositionAfterKeystroke.js → getCursorPositionAfterKeystroke.ts} +8 -8
- package/src/common/textFormat/getSymbolsInPatternWithPosition/{getSymbolsInPatternWithPosition.js → getSymbolsInPatternWithPosition.ts} +7 -2
- package/src/common/textFormat/unformatWithPattern/{unformatWithPattern.js → unformatWithPattern.ts} +3 -2
- package/src/i18n/th.json +3 -3
- package/src/index.ts +3 -0
- package/src/inputWithDisplayFormat/InputWithDisplayFormat.tsx +10 -0
- package/src/inputWithDisplayFormat/index.ts +2 -0
- package/src/inputs/Input.css +0 -4
- package/src/inputs/SelectInput.css +6 -1
- package/src/inputs/SelectInput.less +8 -1
- package/src/inputs/SelectInput.spec.tsx +26 -0
- package/src/inputs/SelectInput.story.tsx +73 -1
- package/src/inputs/SelectInput.tsx +104 -85
- package/src/inputs/TextArea.css +0 -4
- package/src/main.css +6 -17
- package/src/phoneNumberInput/PhoneNumberInput.spec.js +18 -22
- package/src/phoneNumberInput/PhoneNumberInput.tsx +193 -0
- package/src/phoneNumberInput/data/{countries.js → countries.ts} +9 -1
- package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.ts +3 -0
- package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.spec.js → excludeCountries.spec.ts} +1 -1
- package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.js → excludeCountries.ts} +6 -5
- package/src/phoneNumberInput/utils/explodeNumberModel/{explodeNumberModel.spec.js → explodeNumberModel.spec.ts} +1 -1
- package/src/phoneNumberInput/utils/explodeNumberModel/index.ts +24 -0
- package/src/phoneNumberInput/utils/findCountryByCode/{findCountryByCode.spec.js → findCountryByCode.spec.ts} +0 -1
- package/src/phoneNumberInput/utils/findCountryByCode/index.ts +12 -0
- package/src/phoneNumberInput/utils/findCountryByPrefix/index.ts +12 -0
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.ts +102 -0
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.ts +12 -0
- package/src/phoneNumberInput/utils/{index.js → index.ts} +0 -2
- package/src/phoneNumberInput/utils/isStringNumeric/{isStringNumeric.spec.js → isStringNumeric.spec.ts} +0 -1
- package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.ts +1 -0
- package/src/phoneNumberInput/utils/isValidPhoneNumber/{isValidPhoneNumber.spec.js → isValidPhoneNumber.spec.ts} +1 -1
- package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.ts +7 -0
- package/src/phoneNumberInput/utils/longestMatchingPrefix/index.ts +4 -0
- package/src/phoneNumberInput/utils/setDefaultPrefix/index.ts +20 -0
- package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.ts +6 -0
- package/src/select/Select.css +0 -4
- package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.spec.js +3 -1
- package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.story.tsx +32 -0
- package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.tsx +13 -0
- package/src/textareaWithDisplayFormat/index.ts +2 -0
- package/src/withDisplayFormat/WithDisplayFormat.spec.js +1 -1
- package/src/withDisplayFormat/{WithDisplayFormat.js → WithDisplayFormat.tsx} +127 -107
- package/src/withDisplayFormat/index.ts +2 -0
- package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts +0 -2
- package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts.map +0 -1
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts +0 -2
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts.map +0 -1
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts +0 -3
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts.map +0 -1
- package/build/types/utilities/wrapInFragment.d.ts +0 -3
- package/build/types/utilities/wrapInFragment.d.ts.map +0 -1
- package/src/common/locale/index.js +0 -139
- package/src/inputWithDisplayFormat/InputWithDisplayFormat.js +0 -14
- package/src/inputWithDisplayFormat/index.js +0 -1
- package/src/phoneNumberInput/PhoneNumberInput.js +0 -210
- package/src/phoneNumberInput/data/countries.spec.js +0 -12
- package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.js +0 -4
- package/src/phoneNumberInput/utils/explodeNumberModel/index.js +0 -27
- package/src/phoneNumberInput/utils/filterOptionsForQuery/filterOptionsForQuery.spec.js +0 -36
- package/src/phoneNumberInput/utils/filterOptionsForQuery/index.js +0 -11
- package/src/phoneNumberInput/utils/findCountryByCode/index.js +0 -10
- package/src/phoneNumberInput/utils/findCountryByPrefix/index.js +0 -11
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.js +0 -26
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.js +0 -67
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/index.js +0 -1
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.js +0 -25
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.spec.js +0 -66
- package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.js +0 -1
- package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js +0 -10
- package/src/phoneNumberInput/utils/longestMatchingPrefix/index.js +0 -2
- package/src/phoneNumberInput/utils/setDefaultPrefix/index.js +0 -25
- package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.js +0 -3
- package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.js +0 -14
- package/src/textareaWithDisplayFormat/index.js +0 -1
- package/src/utilities/wrapInFragment.tsx +0 -3
- package/src/withDisplayFormat/index.js +0 -1
- /package/src/phoneNumberInput/{PhoneNumberInput.story.js → PhoneNumberInput.story.tsx} +0 -0
- /package/src/phoneNumberInput/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/cleanNumber/{cleanNumber.spec.js → cleanNumber.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/cleanNumber/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/excludeCountries/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/findCountryByPrefix/{findCountryByPrefix.spec.js → findCountryByPrefix.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/groupCountriesByPrefix/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/isStringNumeric/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/isValidPhoneNumber/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/longestMatchingPrefix/{longestMatchingPrefix.spec.js → longestMatchingPrefix.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/setDefaultPrefix/{setDefaultPrefix.spec.js → setDefaultPrefix.spec.ts} +0 -0
- /package/src/phoneNumberInput/utils/sortArrayByProperty/{index.js → index.ts} +0 -0
- /package/src/phoneNumberInput/utils/sortArrayByProperty/{sortArrayByProperty.spec.js → sortArrayByProperty.spec.ts} +0 -0
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { isArray } from '@transferwise/neptune-validation';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { useState, useEffect } from 'react';
|
|
4
|
-
import { useIntl } from 'react-intl';
|
|
5
|
-
|
|
6
|
-
import { Size } from '../common';
|
|
7
|
-
import { SelectInput, SelectInputOptionContent } from '../inputs/SelectInput';
|
|
8
|
-
|
|
9
|
-
import countries from './data/countries';
|
|
10
|
-
import {
|
|
11
|
-
explodeNumberModel,
|
|
12
|
-
isValidPhoneNumber,
|
|
13
|
-
cleanNumber,
|
|
14
|
-
setDefaultPrefix,
|
|
15
|
-
sortArrayByProperty,
|
|
16
|
-
groupCountriesByPrefix,
|
|
17
|
-
excludeCountries,
|
|
18
|
-
} from './utils';
|
|
19
|
-
|
|
20
|
-
const ALLOWED_PHONE_CHARS = /^$|^[\d-\s]+$/;
|
|
21
|
-
|
|
22
|
-
const PhoneNumberInput = (props) => {
|
|
23
|
-
const {
|
|
24
|
-
id,
|
|
25
|
-
onChange,
|
|
26
|
-
searchPlaceholder,
|
|
27
|
-
disabled,
|
|
28
|
-
required,
|
|
29
|
-
size,
|
|
30
|
-
placeholder,
|
|
31
|
-
onFocus,
|
|
32
|
-
onBlur,
|
|
33
|
-
countryCode,
|
|
34
|
-
selectProps,
|
|
35
|
-
disabledCountries,
|
|
36
|
-
} = props;
|
|
37
|
-
const { locale } = useIntl();
|
|
38
|
-
|
|
39
|
-
const getInitialValue = () => {
|
|
40
|
-
const { initialValue } = props;
|
|
41
|
-
|
|
42
|
-
const cleanValue = initialValue ? cleanNumber(initialValue) : null;
|
|
43
|
-
|
|
44
|
-
if (!cleanValue || !isValidPhoneNumber(cleanValue)) {
|
|
45
|
-
return {
|
|
46
|
-
prefix: setDefaultPrefix(locale, countryCode),
|
|
47
|
-
suffix: '',
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return explodeNumberModel(cleanValue);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const [internalValue, setInternalValue] = useState(getInitialValue());
|
|
55
|
-
const [broadcastedValue, setBroadcastedValue] = useState(null);
|
|
56
|
-
|
|
57
|
-
const getSelectOptions = () => {
|
|
58
|
-
const countriesList = excludeCountries(countries, disabledCountries);
|
|
59
|
-
const listSortedByISO3 = groupCountriesByPrefix(sortArrayByProperty(countriesList, 'iso3'));
|
|
60
|
-
|
|
61
|
-
return listSortedByISO3.map((option) => {
|
|
62
|
-
const { phone, iso3, iso2, name } = option;
|
|
63
|
-
let note = '';
|
|
64
|
-
|
|
65
|
-
if (iso3) {
|
|
66
|
-
note = isArray(iso3) ? iso3.join(', ') : iso3;
|
|
67
|
-
} else if (iso2) {
|
|
68
|
-
note = isArray(iso2) ? iso2.join(', ') : iso2;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
type: 'option',
|
|
73
|
-
value: {
|
|
74
|
-
value: phone,
|
|
75
|
-
label: phone,
|
|
76
|
-
note: note,
|
|
77
|
-
},
|
|
78
|
-
filterMatchers: [phone, note, name],
|
|
79
|
-
};
|
|
80
|
-
});
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const options = getSelectOptions();
|
|
84
|
-
|
|
85
|
-
const onPrefixChange = ({ value }) => {
|
|
86
|
-
setInternalValue({ prefix: value, suffix: internalValue.suffix });
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const onSuffixChange = (event) => {
|
|
90
|
-
const { value = '' } = event.target;
|
|
91
|
-
|
|
92
|
-
if (ALLOWED_PHONE_CHARS.test(value)) {
|
|
93
|
-
setInternalValue({ prefix: internalValue.prefix, suffix: value });
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const onPaste = (event) => {
|
|
98
|
-
if (!event.nativeEvent.clipboardData) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const pastedValue = (event.nativeEvent.clipboardData.getData('text/plain') || '').replace(
|
|
103
|
-
/(\s|-)+/g,
|
|
104
|
-
'',
|
|
105
|
-
);
|
|
106
|
-
const { prefix: pastedPrefix, suffix: pastedSuffix } = explodeNumberModel(pastedValue);
|
|
107
|
-
const selectedPrefix = options.find(({ value }) => value.value === pastedPrefix);
|
|
108
|
-
|
|
109
|
-
if (selectedPrefix && ALLOWED_PHONE_CHARS.test(pastedSuffix)) {
|
|
110
|
-
setInternalValue({ prefix: pastedPrefix, suffix: pastedSuffix });
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
if (broadcastedValue === null) {
|
|
116
|
-
return setBroadcastedValue(internalValue);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const internalPhoneNumber = internalValue.prefix + internalValue.suffix;
|
|
120
|
-
const broadcastedPhoneNumber = broadcastedValue.prefix + broadcastedValue.suffix;
|
|
121
|
-
|
|
122
|
-
if (internalPhoneNumber === broadcastedPhoneNumber) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const newValue = isValidPhoneNumber(internalPhoneNumber)
|
|
127
|
-
? cleanNumber(internalPhoneNumber)
|
|
128
|
-
: null;
|
|
129
|
-
|
|
130
|
-
onChange(newValue, internalValue.prefix);
|
|
131
|
-
setBroadcastedValue(internalValue);
|
|
132
|
-
}, [onChange, broadcastedValue, internalValue]);
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
<div className="tw-telephone">
|
|
136
|
-
<div className="tw-telephone__country-select">
|
|
137
|
-
<SelectInput
|
|
138
|
-
placeholder="Select an option..."
|
|
139
|
-
items={options}
|
|
140
|
-
value={options.find((item) => item.value.value === internalValue.prefix)?.value}
|
|
141
|
-
renderValue={(option, withinTrigger) => (
|
|
142
|
-
<SelectInputOptionContent
|
|
143
|
-
title={option.label}
|
|
144
|
-
note={withinTrigger ? undefined : option.note}
|
|
145
|
-
/>
|
|
146
|
-
)}
|
|
147
|
-
filterable
|
|
148
|
-
filterPlaceholder={searchPlaceholder}
|
|
149
|
-
disabled={disabled}
|
|
150
|
-
size={size}
|
|
151
|
-
onChange={onPrefixChange}
|
|
152
|
-
{...selectProps}
|
|
153
|
-
/>
|
|
154
|
-
</div>
|
|
155
|
-
<div className="tw-telephone__number-input">
|
|
156
|
-
<div className={`input-group input-group-${size}`}>
|
|
157
|
-
<input
|
|
158
|
-
id={id}
|
|
159
|
-
autoComplete="tel-national"
|
|
160
|
-
name="phoneNumber"
|
|
161
|
-
inputMode="numeric"
|
|
162
|
-
value={internalValue.suffix}
|
|
163
|
-
className="form-control"
|
|
164
|
-
disabled={disabled}
|
|
165
|
-
required={required}
|
|
166
|
-
placeholder={placeholder}
|
|
167
|
-
onChange={onSuffixChange}
|
|
168
|
-
onPaste={onPaste}
|
|
169
|
-
onFocus={onFocus}
|
|
170
|
-
onBlur={onBlur}
|
|
171
|
-
/>
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
</div>
|
|
175
|
-
);
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
PhoneNumberInput.propTypes = {
|
|
179
|
-
id: PropTypes.string,
|
|
180
|
-
required: PropTypes.bool,
|
|
181
|
-
disabled: PropTypes.bool,
|
|
182
|
-
initialValue: PropTypes.string,
|
|
183
|
-
onChange: PropTypes.func.isRequired,
|
|
184
|
-
onFocus: PropTypes.func,
|
|
185
|
-
onBlur: PropTypes.func,
|
|
186
|
-
countryCode: PropTypes.string,
|
|
187
|
-
searchPlaceholder: PropTypes.string,
|
|
188
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
189
|
-
placeholder: PropTypes.string,
|
|
190
|
-
selectProps: PropTypes.object,
|
|
191
|
-
/** List of iso3 codes of countries to remove from the list */
|
|
192
|
-
disabledCountries: PropTypes.arrayOf(PropTypes.string),
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
PhoneNumberInput.defaultProps = {
|
|
196
|
-
id: null,
|
|
197
|
-
required: false,
|
|
198
|
-
disabled: false,
|
|
199
|
-
initialValue: null,
|
|
200
|
-
onFocus() {},
|
|
201
|
-
onBlur() {},
|
|
202
|
-
countryCode: null,
|
|
203
|
-
searchPlaceholder: 'Prefix',
|
|
204
|
-
size: Size.MEDIUM,
|
|
205
|
-
placeholder: '',
|
|
206
|
-
selectProps: {},
|
|
207
|
-
disabledCountries: [],
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
export default PhoneNumberInput;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import countries from './countries';
|
|
2
|
-
|
|
3
|
-
describe('Given a list of countries', () => {
|
|
4
|
-
countries.forEach((country) => {
|
|
5
|
-
it('each country should have a valid format', () => {
|
|
6
|
-
expect(country).toHaveProperty('phone');
|
|
7
|
-
expect(country).toHaveProperty('name');
|
|
8
|
-
expect(country).toHaveProperty('iso3');
|
|
9
|
-
expect(country).toHaveProperty('iso2');
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { findCountryByPrefix } from '../findCountryByPrefix';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Given a sting in a valid format ex:'+447573135343' it returns an object of shape
|
|
5
|
-
* {prefix=+44 ,suffix=7573135343}
|
|
6
|
-
*
|
|
7
|
-
* @param {string} number - a string that defines a phone number.
|
|
8
|
-
* @returns {{prefix: (string|*), suffix: string, format: string}}
|
|
9
|
-
*/
|
|
10
|
-
export const explodeNumberModel = (number) => {
|
|
11
|
-
let prefix = '';
|
|
12
|
-
let suffix = '';
|
|
13
|
-
let format = '';
|
|
14
|
-
const country = findCountryByPrefix(number);
|
|
15
|
-
|
|
16
|
-
if (country) {
|
|
17
|
-
prefix = country.phone;
|
|
18
|
-
suffix = number.slice(country.phone.length);
|
|
19
|
-
format = country.phoneFormat || '';
|
|
20
|
-
} else {
|
|
21
|
-
prefix = '';
|
|
22
|
-
suffix = number.slice(1);
|
|
23
|
-
format = '';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return { prefix, suffix, format };
|
|
27
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { filterOptionsForQuery } from '..';
|
|
2
|
-
|
|
3
|
-
const OPTIONS = [
|
|
4
|
-
{
|
|
5
|
-
name: 'test1',
|
|
6
|
-
iso2: 'TT',
|
|
7
|
-
iso3: 'TT1',
|
|
8
|
-
phone: '+93',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
name: 'something',
|
|
12
|
-
iso2: 'ST',
|
|
13
|
-
iso3: 'SMT',
|
|
14
|
-
phone: '+33',
|
|
15
|
-
},
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
describe('filterOptionsForQuery', () => {
|
|
19
|
-
it('filters options based on all properties', () => {
|
|
20
|
-
const option1 = OPTIONS[0];
|
|
21
|
-
const option2 = OPTIONS[1];
|
|
22
|
-
|
|
23
|
-
expect(filterOptionsForQuery(OPTIONS, option1.name)).toStrictEqual([option1]);
|
|
24
|
-
expect(filterOptionsForQuery(OPTIONS, option1.iso2)).toStrictEqual([option1]);
|
|
25
|
-
expect(filterOptionsForQuery(OPTIONS, option1.iso3)).toStrictEqual([option1]);
|
|
26
|
-
expect(filterOptionsForQuery(OPTIONS, option1.phone)).toStrictEqual([option1]);
|
|
27
|
-
expect(filterOptionsForQuery(OPTIONS, option2.name)).toStrictEqual([option2]);
|
|
28
|
-
expect(filterOptionsForQuery(OPTIONS, option2.iso2)).toStrictEqual([option2]);
|
|
29
|
-
expect(filterOptionsForQuery(OPTIONS, option2.iso3)).toStrictEqual([option2]);
|
|
30
|
-
expect(filterOptionsForQuery(OPTIONS, option2.phone)).toStrictEqual([option2]);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should return an emtpy array if option cannot be found', () => {
|
|
34
|
-
expect(filterOptionsForQuery(OPTIONS, 'AA')).toStrictEqual([]);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { isOptionAndFitsQuery } from '../isOptionAndFitsQuery';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Filters a set of options based on search string
|
|
5
|
-
*
|
|
6
|
-
* @param options
|
|
7
|
-
* @param query
|
|
8
|
-
* @returns {*}
|
|
9
|
-
*/
|
|
10
|
-
export const filterOptionsForQuery = (options, query) =>
|
|
11
|
-
options.filter((option) => isOptionAndFitsQuery(option, query));
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import countries from '../../data/countries';
|
|
2
|
-
import { longestMatchingPrefix } from '../longestMatchingPrefix';
|
|
3
|
-
|
|
4
|
-
export const findCountryByCode = (code) => {
|
|
5
|
-
let matchingCodes;
|
|
6
|
-
if (code && code.length === 2) {
|
|
7
|
-
matchingCodes = countries.filter((country) => code.toUpperCase() === country.iso2);
|
|
8
|
-
}
|
|
9
|
-
return matchingCodes && matchingCodes.length > 0 ? longestMatchingPrefix(matchingCodes) : null;
|
|
10
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import countries from '../../data/countries';
|
|
2
|
-
import { longestMatchingPrefix } from '../longestMatchingPrefix';
|
|
3
|
-
|
|
4
|
-
export const findCountryByPrefix = (number) => {
|
|
5
|
-
let matchingCodes = null;
|
|
6
|
-
if (number && number.length > 1) {
|
|
7
|
-
matchingCodes = countries.filter((country) => number.indexOf(country.phone) === 0);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
return matchingCodes && matchingCodes.length > 0 ? longestMatchingPrefix(matchingCodes) : null;
|
|
11
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { isArray } from '@transferwise/neptune-validation';
|
|
2
|
-
|
|
3
|
-
export const groupCountriesByPrefix = (countries) => {
|
|
4
|
-
const groupedArray = countries.reduce((accumulator, country) => {
|
|
5
|
-
const { name, iso2, iso3, phone } = country;
|
|
6
|
-
if (accumulator[phone]) {
|
|
7
|
-
const previousValue = accumulator[phone];
|
|
8
|
-
accumulator[phone] = {
|
|
9
|
-
...previousValue,
|
|
10
|
-
name: isArray(previousValue.name)
|
|
11
|
-
? [...previousValue.name, name]
|
|
12
|
-
: [previousValue.name, name],
|
|
13
|
-
iso2: isArray(previousValue.iso2)
|
|
14
|
-
? [...previousValue.iso2, iso2]
|
|
15
|
-
: [previousValue.iso2, iso2],
|
|
16
|
-
iso3: isArray(previousValue.iso3)
|
|
17
|
-
? [...previousValue.iso3, iso3]
|
|
18
|
-
: [previousValue.iso3, iso3],
|
|
19
|
-
};
|
|
20
|
-
} else {
|
|
21
|
-
accumulator[phone] = country;
|
|
22
|
-
}
|
|
23
|
-
return accumulator;
|
|
24
|
-
}, {});
|
|
25
|
-
return Object.values(groupedArray);
|
|
26
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { groupCountriesByPrefix } from '.';
|
|
2
|
-
|
|
3
|
-
const countries = [
|
|
4
|
-
{
|
|
5
|
-
name: 'Canada',
|
|
6
|
-
iso2: 'CA',
|
|
7
|
-
iso3: 'CAN',
|
|
8
|
-
phone: '+1',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
name: 'United States of America',
|
|
12
|
-
iso2: 'US',
|
|
13
|
-
iso3: 'USA',
|
|
14
|
-
phone: '+1',
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
name: 'United States Minor Outlying Islands',
|
|
18
|
-
iso2: 'UM',
|
|
19
|
-
iso3: 'UMI',
|
|
20
|
-
phone: '+1',
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
name: 'United Kingdom',
|
|
24
|
-
iso2: 'GB',
|
|
25
|
-
iso3: 'GBR',
|
|
26
|
-
phone: '+44',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: 'Guernsey',
|
|
30
|
-
iso2: 'GG',
|
|
31
|
-
iso3: 'GGY',
|
|
32
|
-
phone: '+44',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
name: 'Guinea',
|
|
36
|
-
iso2: 'GN',
|
|
37
|
-
iso3: 'GIN',
|
|
38
|
-
phone: '+224',
|
|
39
|
-
},
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const groupedCountries = [
|
|
43
|
-
{
|
|
44
|
-
name: ['Canada', 'United States of America', 'United States Minor Outlying Islands'],
|
|
45
|
-
iso2: ['CA', 'US', 'UM'],
|
|
46
|
-
iso3: ['CAN', 'USA', 'UMI'],
|
|
47
|
-
phone: '+1',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: ['United Kingdom', 'Guernsey'],
|
|
51
|
-
iso2: ['GB', 'GG'],
|
|
52
|
-
iso3: ['GBR', 'GGY'],
|
|
53
|
-
phone: '+44',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: 'Guinea',
|
|
57
|
-
iso2: 'GN',
|
|
58
|
-
iso3: 'GIN',
|
|
59
|
-
phone: '+224',
|
|
60
|
-
},
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
describe('groupCountriesByPrefix', () => {
|
|
64
|
-
it('groups countries by prefix', () => {
|
|
65
|
-
expect(groupCountriesByPrefix(countries)).toStrictEqual(groupedCountries);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { isOptionAndFitsQuery, startsWith } from './isOptionAndFitsQuery';
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { isArray } from '@transferwise/neptune-validation';
|
|
2
|
-
/**
|
|
3
|
-
* Checks if query is contained into object properties.
|
|
4
|
-
*
|
|
5
|
-
* @param {object} option - the select option
|
|
6
|
-
* @param {string} query - the current search query
|
|
7
|
-
* @returns {boolean}
|
|
8
|
-
*/
|
|
9
|
-
export const isOptionAndFitsQuery = (option, query) =>
|
|
10
|
-
startsWith(option.iso3, query) ||
|
|
11
|
-
startsWith(option.iso2, query) ||
|
|
12
|
-
startsWith(option.name, query) ||
|
|
13
|
-
startsWith(option.phone, query);
|
|
14
|
-
|
|
15
|
-
export const startsWith = (property, query) => {
|
|
16
|
-
if (isArray(property)) {
|
|
17
|
-
return (
|
|
18
|
-
property.filter((proper) => normalizeValue(proper).indexOf(normalizeValue(query)) === 0)
|
|
19
|
-
.length > 0
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
return normalizeValue(property).indexOf(normalizeValue(query)) === 0;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const normalizeValue = (value) => value.toLowerCase().replace('+', '');
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { startsWith, isOptionAndFitsQuery } from '.';
|
|
2
|
-
|
|
3
|
-
const DATA_TEST = [
|
|
4
|
-
{
|
|
5
|
-
name: 'test1',
|
|
6
|
-
iso2: 'TT',
|
|
7
|
-
iso3: 'TT1',
|
|
8
|
-
phone: '+93',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
name: 'test1',
|
|
12
|
-
iso2: ['TT', 'AA'],
|
|
13
|
-
iso3: 'TT1',
|
|
14
|
-
phone: '+93',
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
name: 'something',
|
|
18
|
-
iso2: 'ST',
|
|
19
|
-
iso3: 'SMT',
|
|
20
|
-
phone: '+33',
|
|
21
|
-
},
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
describe('isOptionAndFitsQuery', () => {
|
|
25
|
-
describe('when option is given', () => {
|
|
26
|
-
it('should return true if query is relevant', () => {
|
|
27
|
-
expect(isOptionAndFitsQuery(DATA_TEST[0], 'TT')).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should return true if query is relevant and one of the array values', () => {
|
|
31
|
-
expect(isOptionAndFitsQuery(DATA_TEST[1], 'TT')).toBe(true);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should return false if query is not relevant and not one of the array values', () => {
|
|
35
|
-
expect(isOptionAndFitsQuery(DATA_TEST[1], 'BB')).toBe(false);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should return false if query is not relevant', () => {
|
|
39
|
-
expect(isOptionAndFitsQuery(DATA_TEST[0], 'AA')).toBe(false);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe('startWith', () => {
|
|
45
|
-
describe('when property is given', () => {
|
|
46
|
-
it('returns true if any of the values starts with the query', () => {
|
|
47
|
-
expect(startsWith('AA', 'AA')).toBe(true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it(`returns false if value doesn't start with`, () => {
|
|
51
|
-
expect(startsWith('AABB', 'BB')).toBe(false);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should return true if query is contained in grouped options', () => {
|
|
55
|
-
expect(startsWith(['AA', 'BB'], 'BB')).toBe(true);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("returns false if any value in an array doesn't start with", () => {
|
|
59
|
-
expect(startsWith(['CCAA', 'CCBB'], 'BB')).toBe(false);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('returns false for an empty value', () => {
|
|
63
|
-
expect(startsWith('', 'BB')).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const isStringNumeric = (value) => /^\+?[\d-\s]+$/.test(value);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param phoneNumber
|
|
4
|
-
* @returns {boolean} - returns true for number that starts with '+' and contains a mix of digits and spaces with
|
|
5
|
-
* at least 4 digits.
|
|
6
|
-
*/
|
|
7
|
-
export const isValidPhoneNumber = (phoneNumber) =>
|
|
8
|
-
/^\+[\d-\s]+$/.test(phoneNumber) &&
|
|
9
|
-
phoneNumber.match(/\d+/g) &&
|
|
10
|
-
phoneNumber.match(/\d+/g).join('').length >= 4;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { getCountryFromLocale } from '../../../common/locale';
|
|
2
|
-
import { findCountryByCode } from '../findCountryByCode';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Default phone code, the UK one `+44`
|
|
6
|
-
*/
|
|
7
|
-
const DEFAULT_PHONE_CODE = '+44';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Given a valid locale it returns the correspondent prefix if found or +44 otherwise.
|
|
11
|
-
*
|
|
12
|
-
* @param {string} locale - a string that represent the locale ex:'es-ES'
|
|
13
|
-
* @param countryCode
|
|
14
|
-
* @returns {string}
|
|
15
|
-
*/
|
|
16
|
-
export const setDefaultPrefix = (locale, countryCode) => {
|
|
17
|
-
const country =
|
|
18
|
-
findCountryByCode(countryCode) ||
|
|
19
|
-
// when `locale` code has explicit region: `en-GB`, `en-US`, `ar-AE`
|
|
20
|
-
findCountryByCode(getCountryFromLocale(locale)) ||
|
|
21
|
-
// when `locale` code is only two chars value: `fr`, `es`
|
|
22
|
-
findCountryByCode(locale);
|
|
23
|
-
|
|
24
|
-
return country?.phone || DEFAULT_PHONE_CODE;
|
|
25
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types';
|
|
2
|
-
|
|
3
|
-
import WithDisplayFormat from '../withDisplayFormat';
|
|
4
|
-
|
|
5
|
-
const TextareaWithDisplayFormat = (props) => (
|
|
6
|
-
<WithDisplayFormat {...props} render={(renderProps) => <textarea {...renderProps} />} />
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
TextareaWithDisplayFormat.propTypes = {
|
|
10
|
-
displayPattern: PropTypes.string.isRequired,
|
|
11
|
-
onChange: PropTypes.func.isRequired,
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default TextareaWithDisplayFormat;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './TextareaWithDisplayFormat';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './WithDisplayFormat';
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|