@transferwise/components 0.0.0-experimental-85b9dd1 → 0.0.0-experimental-0db2ae7
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/index.esm.js +335 -234
- package/build/index.esm.js.map +1 -1
- package/build/index.js +336 -235
- package/build/index.js.map +1 -1
- package/build/types/common/locale/index.d.ts +43 -26
- 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 +2 -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/phoneNumberInput/PhoneNumberInput.d.ts +27 -22
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/data/countries.d.ts +10 -5
- 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 +1 -8
- 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 +4 -8
- package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts +2 -0
- package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts.map +1 -0
- 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 +1 -2
- 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 +13 -11
- package/build/types/phoneNumberInput/utils/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts +2 -0
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts.map +1 -0
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts +3 -0
- package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts.map +1 -0
- 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 +1 -6
- package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts +1 -2
- package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts.map +1 -1
- package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts +1 -7
- 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 +54 -82
- 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 +1 -1
- package/src/common/locale/index.js +139 -0
- package/src/common/locale/{index.spec.ts → index.spec.js} +4 -4
- 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/index.ts +2 -0
- package/src/inputWithDisplayFormat/InputWithDisplayFormat.tsx +10 -0
- package/src/inputWithDisplayFormat/index.ts +2 -0
- package/src/phoneNumberInput/PhoneNumberInput.js +210 -0
- package/src/phoneNumberInput/PhoneNumberInput.spec.js +22 -18
- package/src/phoneNumberInput/data/{countries.ts → countries.js} +1 -9
- package/src/phoneNumberInput/data/countries.spec.js +12 -0
- package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.js +4 -0
- package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.ts → excludeCountries.js} +5 -6
- package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.spec.ts → excludeCountries.spec.js} +1 -1
- package/src/phoneNumberInput/utils/explodeNumberModel/{explodeNumberModel.spec.ts → explodeNumberModel.spec.js} +1 -1
- package/src/phoneNumberInput/utils/explodeNumberModel/index.js +27 -0
- package/src/phoneNumberInput/utils/filterOptionsForQuery/filterOptionsForQuery.spec.js +36 -0
- package/src/phoneNumberInput/utils/filterOptionsForQuery/index.js +11 -0
- package/src/phoneNumberInput/utils/findCountryByCode/{findCountryByCode.spec.ts → findCountryByCode.spec.js} +1 -0
- package/src/phoneNumberInput/utils/findCountryByCode/index.js +10 -0
- package/src/phoneNumberInput/utils/findCountryByPrefix/index.js +11 -0
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.js +26 -0
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.js +67 -0
- package/src/phoneNumberInput/utils/{index.ts → index.js} +2 -0
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/index.js +1 -0
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.js +25 -0
- package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.spec.js +66 -0
- package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.js +1 -0
- package/src/phoneNumberInput/utils/isStringNumeric/{isStringNumeric.spec.ts → isStringNumeric.spec.js} +1 -0
- package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js +10 -0
- package/src/phoneNumberInput/utils/isValidPhoneNumber/{isValidPhoneNumber.spec.ts → isValidPhoneNumber.spec.js} +1 -1
- package/src/phoneNumberInput/utils/longestMatchingPrefix/index.js +2 -0
- package/src/phoneNumberInput/utils/setDefaultPrefix/index.js +25 -0
- package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.js +3 -0
- 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/src/common/locale/index.ts +0 -96
- package/src/inputWithDisplayFormat/InputWithDisplayFormat.js +0 -14
- package/src/inputWithDisplayFormat/index.js +0 -1
- package/src/phoneNumberInput/PhoneNumberInput.tsx +0 -193
- package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.ts +0 -3
- package/src/phoneNumberInput/utils/explodeNumberModel/index.ts +0 -24
- package/src/phoneNumberInput/utils/findCountryByCode/index.ts +0 -12
- package/src/phoneNumberInput/utils/findCountryByPrefix/index.ts +0 -12
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.ts +0 -102
- package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.ts +0 -12
- package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.ts +0 -1
- package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.ts +0 -7
- package/src/phoneNumberInput/utils/longestMatchingPrefix/index.ts +0 -4
- package/src/phoneNumberInput/utils/setDefaultPrefix/index.ts +0 -20
- package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.ts +0 -6
- package/src/textareaWithDisplayFormat/TextareaWithDisplayFormat.js +0 -14
- package/src/textareaWithDisplayFormat/index.js +0 -1
- package/src/withDisplayFormat/index.js +0 -1
- /package/src/phoneNumberInput/{PhoneNumberInput.story.tsx → PhoneNumberInput.story.js} +0 -0
- /package/src/phoneNumberInput/{index.ts → index.js} +0 -0
- /package/src/phoneNumberInput/utils/cleanNumber/{cleanNumber.spec.ts → cleanNumber.spec.js} +0 -0
- /package/src/phoneNumberInput/utils/cleanNumber/{index.ts → index.js} +0 -0
- /package/src/phoneNumberInput/utils/excludeCountries/{index.ts → index.js} +0 -0
- /package/src/phoneNumberInput/utils/findCountryByPrefix/{findCountryByPrefix.spec.ts → findCountryByPrefix.spec.js} +0 -0
- /package/src/phoneNumberInput/utils/groupCountriesByPrefix/{index.ts → index.js} +0 -0
- /package/src/phoneNumberInput/utils/isStringNumeric/{index.ts → index.js} +0 -0
- /package/src/phoneNumberInput/utils/isValidPhoneNumber/{index.ts → index.js} +0 -0
- /package/src/phoneNumberInput/utils/longestMatchingPrefix/{longestMatchingPrefix.spec.ts → longestMatchingPrefix.spec.js} +0 -0
- /package/src/phoneNumberInput/utils/setDefaultPrefix/{setDefaultPrefix.spec.ts → setDefaultPrefix.spec.js} +0 -0
- /package/src/phoneNumberInput/utils/sortArrayByProperty/{index.ts → index.js} +0 -0
- /package/src/phoneNumberInput/utils/sortArrayByProperty/{sortArrayByProperty.spec.ts → sortArrayByProperty.spec.js} +0 -0
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { Direction } from '..';
|
|
2
|
-
|
|
3
|
-
export const DEFAULT_LANG = 'en';
|
|
4
|
-
export const DEFAULT_LOCALE = 'en-GB';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Languages written right-to-left.
|
|
8
|
-
*/
|
|
9
|
-
export const RTL_LANGUAGES = ['ar', 'he'];
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @deprecated The source of truth for supported languages lives in Crab.
|
|
13
|
-
*/
|
|
14
|
-
export const SUPPORTED_LANGUAGES = [
|
|
15
|
-
DEFAULT_LANG,
|
|
16
|
-
'de',
|
|
17
|
-
'es',
|
|
18
|
-
'fr',
|
|
19
|
-
'hu',
|
|
20
|
-
'id',
|
|
21
|
-
'it',
|
|
22
|
-
'ja',
|
|
23
|
-
'pl',
|
|
24
|
-
'pt',
|
|
25
|
-
'ro',
|
|
26
|
-
'ru',
|
|
27
|
-
'th',
|
|
28
|
-
'tr',
|
|
29
|
-
'uk',
|
|
30
|
-
'zh',
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Verifies and adjusts locale, replacing `_` with `-`.
|
|
35
|
-
*
|
|
36
|
-
* @param locale `es`, `es_ES`, `en-GB`, `en`, `ja`, `ja-JP`, etc.
|
|
37
|
-
* @returns `null` if locale is unrecognized by `Intl.Locale`.
|
|
38
|
-
*/
|
|
39
|
-
export function adjustLocale(locale: string) {
|
|
40
|
-
const localeTrimmed = locale?.trim();
|
|
41
|
-
if (localeTrimmed) {
|
|
42
|
-
try {
|
|
43
|
-
return new Intl.Locale(localeTrimmed.replace('_', '-')).baseName;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
// eslint-disable-next-line no-console
|
|
46
|
-
console.error(error);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Provides corresponding lang (iso2) for provided locale.
|
|
54
|
-
*
|
|
55
|
-
* @deprecated The use of this function almost always breaks language variants
|
|
56
|
-
* e.g. Simplified and Traditional Chinese.
|
|
57
|
-
* There should be no use case for this function.
|
|
58
|
-
* To select the correct translations from a translations object, pass the
|
|
59
|
-
* locale directly into Crab's getLocalisedMessages.
|
|
60
|
-
* @param locale `es`, `es-ES`, `en-GB`, `en`, `ja`, `ja-JP`, etc.
|
|
61
|
-
* @returns Two-letter ISO 639-1 language code, falling back to `null` if locale is invalid or language is unsupported.
|
|
62
|
-
*/
|
|
63
|
-
export function getLangFromLocale(locale: string) {
|
|
64
|
-
const adjustedLocale = adjustLocale(locale);
|
|
65
|
-
if (adjustedLocale != null) {
|
|
66
|
-
const { language } = new Intl.Locale(adjustedLocale);
|
|
67
|
-
if (SUPPORTED_LANGUAGES.includes(language)) {
|
|
68
|
-
return language;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Provides corresponding country code (iso2) for locales code with explicit region value.
|
|
76
|
-
*
|
|
77
|
-
* @param locale `es-ES`, `en-GB`, `ja-JP`, etc.
|
|
78
|
-
* @returns `null` if the locale is invalid or the region can‘t be identified.
|
|
79
|
-
*/
|
|
80
|
-
export function getCountryFromLocale(locale: string) {
|
|
81
|
-
const adjustedLocale = adjustLocale(locale);
|
|
82
|
-
return adjustedLocale != null ? new Intl.Locale(adjustedLocale).region ?? null : null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Provides the layout direction for a given locale.
|
|
87
|
-
*
|
|
88
|
-
* @param locale `es`, `es-ES`, `en-GB`, `en`, `ja`, `ja-JP`, etc.
|
|
89
|
-
* @returns The layout direction based on the locale, falling back to `Direction.LTR` if the locale is invalid or unsupported.
|
|
90
|
-
*/
|
|
91
|
-
export function getDirectionFromLocale(locale: string) {
|
|
92
|
-
const adjustedLocale = adjustLocale(locale);
|
|
93
|
-
return adjustedLocale != null && RTL_LANGUAGES.includes(new Intl.Locale(adjustedLocale).language)
|
|
94
|
-
? Direction.RTL
|
|
95
|
-
: Direction.LTR;
|
|
96
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types';
|
|
2
|
-
|
|
3
|
-
import WithDisplayFormat from '../withDisplayFormat';
|
|
4
|
-
|
|
5
|
-
const InputWithDisplayFormat = (props) => (
|
|
6
|
-
<WithDisplayFormat {...props} render={(renderProps) => <input {...renderProps} />} />
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
InputWithDisplayFormat.propTypes = {
|
|
10
|
-
displayPattern: PropTypes.string.isRequired,
|
|
11
|
-
onChange: PropTypes.func.isRequired,
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default InputWithDisplayFormat;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './InputWithDisplayFormat';
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
2
|
-
import { useIntl } from 'react-intl';
|
|
3
|
-
|
|
4
|
-
import { Size, SizeLarge, SizeMedium, SizeSmall } from '../common';
|
|
5
|
-
import { SelectInput, SelectInputOptionContent, SelectInputProps } from '../inputs/SelectInput';
|
|
6
|
-
|
|
7
|
-
import countries from './data/countries';
|
|
8
|
-
import {
|
|
9
|
-
explodeNumberModel,
|
|
10
|
-
isValidPhoneNumber,
|
|
11
|
-
cleanNumber,
|
|
12
|
-
setDefaultPrefix,
|
|
13
|
-
sortArrayByProperty,
|
|
14
|
-
groupCountriesByPrefix,
|
|
15
|
-
excludeCountries,
|
|
16
|
-
findCountryByPrefix,
|
|
17
|
-
} from './utils';
|
|
18
|
-
import { PhoneNumber } from './utils/explodeNumberModel';
|
|
19
|
-
|
|
20
|
-
const ALLOWED_PHONE_CHARS = /^$|^[\d-\s]+$/;
|
|
21
|
-
|
|
22
|
-
export interface PhoneNumberInputProps {
|
|
23
|
-
id?: string;
|
|
24
|
-
required?: boolean;
|
|
25
|
-
disabled?: boolean;
|
|
26
|
-
initialValue?: string;
|
|
27
|
-
onChange: (value: string | null, prefix: string) => void;
|
|
28
|
-
onFocus?: React.FocusEventHandler<HTMLInputElement>;
|
|
29
|
-
onBlur?: React.FocusEventHandler<HTMLInputElement>;
|
|
30
|
-
countryCode?: string;
|
|
31
|
-
searchPlaceholder?: string;
|
|
32
|
-
size?: SizeSmall | SizeMedium | SizeLarge;
|
|
33
|
-
placeholder?: string;
|
|
34
|
-
selectProps?: Partial<SelectInputProps<string | null>>;
|
|
35
|
-
/** List of iso3 codes of countries to remove from the list */
|
|
36
|
-
disabledCountries?: string[];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const defaultSelectProps = {} satisfies PhoneNumberInputProps['selectProps'];
|
|
40
|
-
const defaultDisabledCountries = [] satisfies PhoneNumberInputProps['disabledCountries'];
|
|
41
|
-
|
|
42
|
-
const PhoneNumberInput = ({
|
|
43
|
-
id,
|
|
44
|
-
required,
|
|
45
|
-
disabled,
|
|
46
|
-
initialValue,
|
|
47
|
-
onChange,
|
|
48
|
-
onFocus,
|
|
49
|
-
onBlur,
|
|
50
|
-
countryCode,
|
|
51
|
-
searchPlaceholder = 'Prefix',
|
|
52
|
-
size = Size.MEDIUM,
|
|
53
|
-
placeholder,
|
|
54
|
-
selectProps = defaultSelectProps,
|
|
55
|
-
disabledCountries = defaultDisabledCountries,
|
|
56
|
-
}: PhoneNumberInputProps) => {
|
|
57
|
-
const { locale } = useIntl();
|
|
58
|
-
|
|
59
|
-
const [internalValue, setInternalValue] = useState<PhoneNumber>(() => {
|
|
60
|
-
const cleanValue = initialValue ? cleanNumber(initialValue) : null;
|
|
61
|
-
|
|
62
|
-
if (!cleanValue || !isValidPhoneNumber(cleanValue)) {
|
|
63
|
-
return {
|
|
64
|
-
prefix: setDefaultPrefix(locale, countryCode),
|
|
65
|
-
suffix: '',
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return explodeNumberModel(cleanValue);
|
|
70
|
-
});
|
|
71
|
-
const [broadcastedValue, setBroadcastedValue] = useState<PhoneNumber | null>(null);
|
|
72
|
-
|
|
73
|
-
const countriesByPrefix = useMemo(
|
|
74
|
-
() =>
|
|
75
|
-
groupCountriesByPrefix(
|
|
76
|
-
sortArrayByProperty(excludeCountries(countries, disabledCountries), 'iso3'),
|
|
77
|
-
),
|
|
78
|
-
[disabledCountries],
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const onSuffixChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
|
82
|
-
const suffix = event.target.value;
|
|
83
|
-
if (ALLOWED_PHONE_CHARS.test(suffix)) {
|
|
84
|
-
setInternalValue((prev) => ({ ...prev, suffix }));
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const onPaste: React.ClipboardEventHandler<HTMLInputElement> = (event) => {
|
|
89
|
-
if (!event.nativeEvent.clipboardData) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const pastedValue = (event.nativeEvent.clipboardData.getData('text/plain') || '').replace(
|
|
94
|
-
/(\s|-)+/g,
|
|
95
|
-
'',
|
|
96
|
-
);
|
|
97
|
-
const pastedNumber = explodeNumberModel(pastedValue);
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
pastedNumber.prefix != null &&
|
|
101
|
-
countriesByPrefix.has(pastedNumber.prefix) &&
|
|
102
|
-
ALLOWED_PHONE_CHARS.test(pastedNumber.suffix)
|
|
103
|
-
) {
|
|
104
|
-
setInternalValue(pastedNumber);
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
if (broadcastedValue === null) {
|
|
110
|
-
return setBroadcastedValue(internalValue);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const internalPhoneNumber = `${internalValue.prefix ?? ''}${internalValue.suffix}`;
|
|
114
|
-
const broadcastedPhoneNumber = `${broadcastedValue.prefix ?? ''}${broadcastedValue.suffix}`;
|
|
115
|
-
|
|
116
|
-
if (internalPhoneNumber === broadcastedPhoneNumber) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const newValue = isValidPhoneNumber(internalPhoneNumber)
|
|
121
|
-
? cleanNumber(internalPhoneNumber)
|
|
122
|
-
: null;
|
|
123
|
-
|
|
124
|
-
onChange(
|
|
125
|
-
newValue,
|
|
126
|
-
internalValue.prefix ?? '', // TODO: Allow `null` in public API
|
|
127
|
-
);
|
|
128
|
-
setBroadcastedValue(internalValue);
|
|
129
|
-
}, [onChange, broadcastedValue, internalValue]);
|
|
130
|
-
|
|
131
|
-
return (
|
|
132
|
-
<div className="tw-telephone">
|
|
133
|
-
<div className="tw-telephone__country-select">
|
|
134
|
-
<SelectInput
|
|
135
|
-
placeholder="Select an option…"
|
|
136
|
-
items={[...countriesByPrefix].map(([prefix, countries]) => ({
|
|
137
|
-
type: 'option',
|
|
138
|
-
value: prefix,
|
|
139
|
-
filterMatchers: [
|
|
140
|
-
prefix,
|
|
141
|
-
...countries.map((country) => country.name),
|
|
142
|
-
...countries.map((country) => country.iso3),
|
|
143
|
-
],
|
|
144
|
-
}))}
|
|
145
|
-
value={internalValue.prefix}
|
|
146
|
-
renderValue={(prefix, withinTrigger) => (
|
|
147
|
-
<SelectInputOptionContent
|
|
148
|
-
title={prefix}
|
|
149
|
-
note={
|
|
150
|
-
withinTrigger
|
|
151
|
-
? undefined
|
|
152
|
-
: countriesByPrefix
|
|
153
|
-
.get(prefix)
|
|
154
|
-
?.map((country) => country.iso3)
|
|
155
|
-
.join(', ')
|
|
156
|
-
}
|
|
157
|
-
/>
|
|
158
|
-
)}
|
|
159
|
-
filterable
|
|
160
|
-
filterPlaceholder={searchPlaceholder}
|
|
161
|
-
disabled={disabled}
|
|
162
|
-
size={size}
|
|
163
|
-
onChange={(prefix) => {
|
|
164
|
-
const country = prefix != null ? findCountryByPrefix(prefix) : null;
|
|
165
|
-
setInternalValue((prev) => ({ ...prev, prefix, format: country?.phoneFormat }));
|
|
166
|
-
}}
|
|
167
|
-
{...selectProps}
|
|
168
|
-
/>
|
|
169
|
-
</div>
|
|
170
|
-
<div className="tw-telephone__number-input">
|
|
171
|
-
<div className={`input-group input-group-${size}`}>
|
|
172
|
-
<input
|
|
173
|
-
id={id}
|
|
174
|
-
autoComplete="tel-national"
|
|
175
|
-
name="phoneNumber"
|
|
176
|
-
inputMode="numeric"
|
|
177
|
-
value={internalValue.suffix}
|
|
178
|
-
className="form-control"
|
|
179
|
-
disabled={disabled}
|
|
180
|
-
required={required}
|
|
181
|
-
placeholder={placeholder}
|
|
182
|
-
onChange={onSuffixChange}
|
|
183
|
-
onPaste={onPaste}
|
|
184
|
-
onFocus={onFocus}
|
|
185
|
-
onBlur={onBlur}
|
|
186
|
-
/>
|
|
187
|
-
</div>
|
|
188
|
-
</div>
|
|
189
|
-
</div>
|
|
190
|
-
);
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
export default PhoneNumberInput;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { findCountryByPrefix } from '../findCountryByPrefix';
|
|
2
|
-
|
|
3
|
-
export interface PhoneNumber {
|
|
4
|
-
prefix: string | null;
|
|
5
|
-
suffix: string;
|
|
6
|
-
format?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param number Phone number in a format like "+447573135343"
|
|
11
|
-
*/
|
|
12
|
-
export const explodeNumberModel = (number: string): PhoneNumber => {
|
|
13
|
-
const country = findCountryByPrefix(number);
|
|
14
|
-
return country
|
|
15
|
-
? {
|
|
16
|
-
prefix: country.phone,
|
|
17
|
-
suffix: number.slice(country.phone.length),
|
|
18
|
-
format: country.phoneFormat,
|
|
19
|
-
}
|
|
20
|
-
: {
|
|
21
|
-
prefix: null,
|
|
22
|
-
suffix: number.slice(1),
|
|
23
|
-
};
|
|
24
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import countries from '../../data/countries';
|
|
2
|
-
import { longestMatchingPrefix } from '../longestMatchingPrefix';
|
|
3
|
-
|
|
4
|
-
export const findCountryByCode = (code: string) => {
|
|
5
|
-
if (code.length === 2) {
|
|
6
|
-
const matchingCodes = countries.filter((country) => code.toUpperCase() === country.iso2);
|
|
7
|
-
if (matchingCodes.length > 0) {
|
|
8
|
-
return longestMatchingPrefix(matchingCodes);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return null;
|
|
12
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import countries from '../../data/countries';
|
|
2
|
-
import { longestMatchingPrefix } from '../longestMatchingPrefix';
|
|
3
|
-
|
|
4
|
-
export const findCountryByPrefix = (number: string) => {
|
|
5
|
-
if (number.length > 1) {
|
|
6
|
-
const matchingCodes = countries.filter((country) => number.startsWith(country.phone));
|
|
7
|
-
if (matchingCodes.length > 0) {
|
|
8
|
-
return longestMatchingPrefix(matchingCodes);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return null;
|
|
12
|
-
};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { Country } from '../../data/countries';
|
|
2
|
-
|
|
3
|
-
import { groupCountriesByPrefix } from '.';
|
|
4
|
-
|
|
5
|
-
const countries = [
|
|
6
|
-
{
|
|
7
|
-
name: 'Canada',
|
|
8
|
-
iso2: 'CA',
|
|
9
|
-
iso3: 'CAN',
|
|
10
|
-
phone: '+1',
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
name: 'United States of America',
|
|
14
|
-
iso2: 'US',
|
|
15
|
-
iso3: 'USA',
|
|
16
|
-
phone: '+1',
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
name: 'United States Minor Outlying Islands',
|
|
20
|
-
iso2: 'UM',
|
|
21
|
-
iso3: 'UMI',
|
|
22
|
-
phone: '+1',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: 'United Kingdom',
|
|
26
|
-
iso2: 'GB',
|
|
27
|
-
iso3: 'GBR',
|
|
28
|
-
phone: '+44',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: 'Guernsey',
|
|
32
|
-
iso2: 'GG',
|
|
33
|
-
iso3: 'GGY',
|
|
34
|
-
phone: '+44',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: 'Guinea',
|
|
38
|
-
iso2: 'GN',
|
|
39
|
-
iso3: 'GIN',
|
|
40
|
-
phone: '+224',
|
|
41
|
-
},
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
const groupedCountries = new Map<string, Country[]>([
|
|
45
|
-
[
|
|
46
|
-
'+1',
|
|
47
|
-
[
|
|
48
|
-
{
|
|
49
|
-
name: 'Canada',
|
|
50
|
-
iso2: 'CA',
|
|
51
|
-
iso3: 'CAN',
|
|
52
|
-
phone: '+1',
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: 'United States of America',
|
|
56
|
-
iso2: 'US',
|
|
57
|
-
iso3: 'USA',
|
|
58
|
-
phone: '+1',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'United States Minor Outlying Islands',
|
|
62
|
-
iso2: 'UM',
|
|
63
|
-
iso3: 'UMI',
|
|
64
|
-
phone: '+1',
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
],
|
|
68
|
-
[
|
|
69
|
-
'+44',
|
|
70
|
-
[
|
|
71
|
-
{
|
|
72
|
-
name: 'United Kingdom',
|
|
73
|
-
iso2: 'GB',
|
|
74
|
-
iso3: 'GBR',
|
|
75
|
-
phone: '+44',
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
name: 'Guernsey',
|
|
79
|
-
iso2: 'GG',
|
|
80
|
-
iso3: 'GGY',
|
|
81
|
-
phone: '+44',
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
],
|
|
85
|
-
[
|
|
86
|
-
'+224',
|
|
87
|
-
[
|
|
88
|
-
{
|
|
89
|
-
name: 'Guinea',
|
|
90
|
-
iso2: 'GN',
|
|
91
|
-
iso3: 'GIN',
|
|
92
|
-
phone: '+224',
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
],
|
|
96
|
-
]);
|
|
97
|
-
|
|
98
|
-
describe('groupCountriesByPrefix', () => {
|
|
99
|
-
it('groups countries by prefix', () => {
|
|
100
|
-
expect(groupCountriesByPrefix(countries)).toStrictEqual(groupedCountries);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Country } from '../../data/countries';
|
|
2
|
-
|
|
3
|
-
export const groupCountriesByPrefix = (countries: Country[]) => {
|
|
4
|
-
const countriesByPrefix = new Map<string, Country[]>();
|
|
5
|
-
countries.forEach((country) => {
|
|
6
|
-
countriesByPrefix.set(country.phone, [
|
|
7
|
-
...(countriesByPrefix.get(country.phone) ?? []),
|
|
8
|
-
country,
|
|
9
|
-
]);
|
|
10
|
-
});
|
|
11
|
-
return countriesByPrefix;
|
|
12
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const isStringNumeric = (value: string) => /^\+?[\d-\s]+$/.test(value);
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param phoneNumber
|
|
4
|
-
* @returns True if number that starts with "+" and contains a mix of digits and spaces with at least 4 digits.
|
|
5
|
-
*/
|
|
6
|
-
export const isValidPhoneNumber = (phoneNumber: string) =>
|
|
7
|
-
/^\+[\d-\s]+$/.test(phoneNumber) && (phoneNumber.match(/\d+/g)?.join('').length ?? 0) >= 4;
|
|
@@ -1,20 +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 locale BCP 47 language tag of locale, e.g. `"es-ES"`.
|
|
13
|
-
* @param countryCode Two-letter country code (ISO 3166-1 alpha-2).
|
|
14
|
-
*/
|
|
15
|
-
export const setDefaultPrefix = (locale: string, countryCode?: string) => {
|
|
16
|
-
const country =
|
|
17
|
-
(countryCode != null ? findCountryByCode(countryCode) : null) ??
|
|
18
|
-
findCountryByCode(getCountryFromLocale(locale) ?? locale);
|
|
19
|
-
return country?.phone ?? DEFAULT_PHONE_CODE;
|
|
20
|
-
};
|
|
@@ -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
|