@transferwise/components 46.6.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.
Files changed (133) hide show
  1. package/build/index.esm.js +186 -342
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +185 -341
  4. package/build/index.js.map +1 -1
  5. package/build/main.css +6 -17
  6. package/build/styles/inputs/Input.css +0 -4
  7. package/build/styles/inputs/SelectInput.css +6 -1
  8. package/build/styles/inputs/TextArea.css +0 -4
  9. package/build/styles/main.css +6 -17
  10. package/build/styles/select/Select.css +0 -4
  11. package/build/types/common/locale/index.d.ts +26 -43
  12. package/build/types/common/locale/index.d.ts.map +1 -1
  13. package/build/types/index.d.ts +1 -0
  14. package/build/types/index.d.ts.map +1 -1
  15. package/build/types/inputs/SelectInput.d.ts +6 -5
  16. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  17. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts +22 -27
  18. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
  19. package/build/types/phoneNumberInput/data/countries.d.ts +5 -10
  20. package/build/types/phoneNumberInput/data/countries.d.ts.map +1 -1
  21. package/build/types/phoneNumberInput/index.d.ts +1 -1
  22. package/build/types/phoneNumberInput/index.d.ts.map +1 -1
  23. package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts +1 -1
  24. package/build/types/phoneNumberInput/utils/cleanNumber/cleanNumber.d.ts.map +1 -1
  25. package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts +1 -1
  26. package/build/types/phoneNumberInput/utils/cleanNumber/index.d.ts.map +1 -1
  27. package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts +8 -1
  28. package/build/types/phoneNumberInput/utils/excludeCountries/excludeCountries.d.ts.map +1 -1
  29. package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts +1 -1
  30. package/build/types/phoneNumberInput/utils/excludeCountries/index.d.ts.map +1 -1
  31. package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts +8 -4
  32. package/build/types/phoneNumberInput/utils/explodeNumberModel/index.d.ts.map +1 -1
  33. package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts +1 -1
  34. package/build/types/phoneNumberInput/utils/findCountryByCode/index.d.ts.map +1 -1
  35. package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts +1 -1
  36. package/build/types/phoneNumberInput/utils/findCountryByPrefix/index.d.ts.map +1 -1
  37. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts +2 -1
  38. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.d.ts.map +1 -1
  39. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts +1 -1
  40. package/build/types/phoneNumberInput/utils/groupCountriesByPrefix/index.d.ts.map +1 -1
  41. package/build/types/phoneNumberInput/utils/index.d.ts +11 -13
  42. package/build/types/phoneNumberInput/utils/index.d.ts.map +1 -1
  43. package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts +1 -1
  44. package/build/types/phoneNumberInput/utils/isStringNumeric/index.d.ts.map +1 -1
  45. package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts +1 -1
  46. package/build/types/phoneNumberInput/utils/isStringNumeric/isStringNumeric.d.ts.map +1 -1
  47. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts +1 -1
  48. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/index.d.ts.map +1 -1
  49. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts +6 -1
  50. package/build/types/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.d.ts.map +1 -1
  51. package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts +2 -1
  52. package/build/types/phoneNumberInput/utils/longestMatchingPrefix/index.d.ts.map +1 -1
  53. package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts +7 -1
  54. package/build/types/phoneNumberInput/utils/setDefaultPrefix/index.d.ts.map +1 -1
  55. package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts +1 -1
  56. package/build/types/phoneNumberInput/utils/sortArrayByProperty/index.d.ts.map +1 -1
  57. package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts +1 -1
  58. package/build/types/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.d.ts.map +1 -1
  59. package/package.json +3 -4
  60. package/src/common/locale/{index.spec.js → index.spec.ts} +4 -4
  61. package/src/common/locale/index.ts +96 -0
  62. package/src/index.ts +1 -0
  63. package/src/inputs/Input.css +0 -4
  64. package/src/inputs/SelectInput.css +6 -1
  65. package/src/inputs/SelectInput.less +8 -1
  66. package/src/inputs/SelectInput.spec.tsx +26 -0
  67. package/src/inputs/SelectInput.story.tsx +73 -1
  68. package/src/inputs/SelectInput.tsx +104 -85
  69. package/src/inputs/TextArea.css +0 -4
  70. package/src/main.css +6 -17
  71. package/src/phoneNumberInput/PhoneNumberInput.spec.js +18 -22
  72. package/src/phoneNumberInput/PhoneNumberInput.tsx +193 -0
  73. package/src/phoneNumberInput/data/{countries.js → countries.ts} +9 -1
  74. package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.ts +3 -0
  75. package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.spec.js → excludeCountries.spec.ts} +1 -1
  76. package/src/phoneNumberInput/utils/excludeCountries/{excludeCountries.js → excludeCountries.ts} +6 -5
  77. package/src/phoneNumberInput/utils/explodeNumberModel/{explodeNumberModel.spec.js → explodeNumberModel.spec.ts} +1 -1
  78. package/src/phoneNumberInput/utils/explodeNumberModel/index.ts +24 -0
  79. package/src/phoneNumberInput/utils/findCountryByCode/{findCountryByCode.spec.js → findCountryByCode.spec.ts} +0 -1
  80. package/src/phoneNumberInput/utils/findCountryByCode/index.ts +12 -0
  81. package/src/phoneNumberInput/utils/findCountryByPrefix/index.ts +12 -0
  82. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.ts +102 -0
  83. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.ts +12 -0
  84. package/src/phoneNumberInput/utils/{index.js → index.ts} +0 -2
  85. package/src/phoneNumberInput/utils/isStringNumeric/{isStringNumeric.spec.js → isStringNumeric.spec.ts} +0 -1
  86. package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.ts +1 -0
  87. package/src/phoneNumberInput/utils/isValidPhoneNumber/{isValidPhoneNumber.spec.js → isValidPhoneNumber.spec.ts} +1 -1
  88. package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.ts +7 -0
  89. package/src/phoneNumberInput/utils/longestMatchingPrefix/index.ts +4 -0
  90. package/src/phoneNumberInput/utils/setDefaultPrefix/index.ts +20 -0
  91. package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.ts +6 -0
  92. package/src/select/Select.css +0 -4
  93. package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts +0 -2
  94. package/build/types/phoneNumberInput/utils/filterOptionsForQuery/index.d.ts.map +0 -1
  95. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts +0 -2
  96. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/index.d.ts.map +0 -1
  97. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts +0 -3
  98. package/build/types/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.d.ts.map +0 -1
  99. package/build/types/utilities/wrapInFragment.d.ts +0 -3
  100. package/build/types/utilities/wrapInFragment.d.ts.map +0 -1
  101. package/src/common/locale/index.js +0 -139
  102. package/src/phoneNumberInput/PhoneNumberInput.js +0 -210
  103. package/src/phoneNumberInput/data/countries.spec.js +0 -12
  104. package/src/phoneNumberInput/utils/cleanNumber/cleanNumber.js +0 -4
  105. package/src/phoneNumberInput/utils/explodeNumberModel/index.js +0 -27
  106. package/src/phoneNumberInput/utils/filterOptionsForQuery/filterOptionsForQuery.spec.js +0 -36
  107. package/src/phoneNumberInput/utils/filterOptionsForQuery/index.js +0 -11
  108. package/src/phoneNumberInput/utils/findCountryByCode/index.js +0 -10
  109. package/src/phoneNumberInput/utils/findCountryByPrefix/index.js +0 -11
  110. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.js +0 -26
  111. package/src/phoneNumberInput/utils/groupCountriesByPrefix/groupCountriesByPrefix.spec.js +0 -67
  112. package/src/phoneNumberInput/utils/isOptionAndFitsQuery/index.js +0 -1
  113. package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.js +0 -25
  114. package/src/phoneNumberInput/utils/isOptionAndFitsQuery/isOptionAndFitsQuery.spec.js +0 -66
  115. package/src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.js +0 -1
  116. package/src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js +0 -10
  117. package/src/phoneNumberInput/utils/longestMatchingPrefix/index.js +0 -2
  118. package/src/phoneNumberInput/utils/setDefaultPrefix/index.js +0 -25
  119. package/src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.js +0 -3
  120. package/src/utilities/wrapInFragment.tsx +0 -3
  121. /package/src/phoneNumberInput/{PhoneNumberInput.story.js → PhoneNumberInput.story.tsx} +0 -0
  122. /package/src/phoneNumberInput/{index.js → index.ts} +0 -0
  123. /package/src/phoneNumberInput/utils/cleanNumber/{cleanNumber.spec.js → cleanNumber.spec.ts} +0 -0
  124. /package/src/phoneNumberInput/utils/cleanNumber/{index.js → index.ts} +0 -0
  125. /package/src/phoneNumberInput/utils/excludeCountries/{index.js → index.ts} +0 -0
  126. /package/src/phoneNumberInput/utils/findCountryByPrefix/{findCountryByPrefix.spec.js → findCountryByPrefix.spec.ts} +0 -0
  127. /package/src/phoneNumberInput/utils/groupCountriesByPrefix/{index.js → index.ts} +0 -0
  128. /package/src/phoneNumberInput/utils/isStringNumeric/{index.js → index.ts} +0 -0
  129. /package/src/phoneNumberInput/utils/isValidPhoneNumber/{index.js → index.ts} +0 -0
  130. /package/src/phoneNumberInput/utils/longestMatchingPrefix/{longestMatchingPrefix.spec.js → longestMatchingPrefix.spec.ts} +0 -0
  131. /package/src/phoneNumberInput/utils/setDefaultPrefix/{setDefaultPrefix.spec.js → setDefaultPrefix.spec.ts} +0 -0
  132. /package/src/phoneNumberInput/utils/sortArrayByProperty/{index.js → index.ts} +0 -0
  133. /package/src/phoneNumberInput/utils/sortArrayByProperty/{sortArrayByProperty.spec.js → sortArrayByProperty.spec.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isStringNumeric/index.js"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isStringNumeric/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,2 +1,2 @@
1
- export function isStringNumeric(value: any): boolean;
1
+ export declare const isStringNumeric: (value: string) => boolean;
2
2
  //# sourceMappingURL=isStringNumeric.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"isStringNumeric.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.js"],"names":[],"mappings":"AAAO,qDAA8D"}
1
+ {"version":3,"file":"isStringNumeric.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isStringNumeric/isStringNumeric.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,UAAW,MAAM,YAAgC,CAAC"}
@@ -1,2 +1,2 @@
1
- export { isValidPhoneNumber } from "./isValidPhoneNumber";
1
+ export { isValidPhoneNumber } from './isValidPhoneNumber';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isValidPhoneNumber/index.js"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isValidPhoneNumber/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,2 +1,7 @@
1
- export function isValidPhoneNumber(phoneNumber: any): boolean;
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 declare const isValidPhoneNumber: (phoneNumber: string) => boolean;
2
7
  //# sourceMappingURL=isValidPhoneNumber.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"isValidPhoneNumber.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.js"],"names":[],"mappings":"AAMO,sDAHM,OAAO,CAM4B"}
1
+ {"version":3,"file":"isValidPhoneNumber.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/isValidPhoneNumber/isValidPhoneNumber.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,gBAAiB,MAAM,YACsC,CAAC"}
@@ -1,2 +1,3 @@
1
- export function longestMatchingPrefix(matchingCodes: any): any;
1
+ import { Country } from '../../data/countries';
2
+ export declare const longestMatchingPrefix: (matchingCodes: Country[]) => Country;
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/longestMatchingPrefix/index.js"],"names":[],"mappings":"AAAO,+DACoE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/longestMatchingPrefix/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,eAAO,MAAM,qBAAqB,kBAAmB,OAAO,EAAE,YACa,CAAC"}
@@ -1,2 +1,8 @@
1
- export function setDefaultPrefix(locale: string, countryCode: any): string;
1
+ /**
2
+ * Given a valid locale it returns the correspondent prefix if found or +44 otherwise.
3
+ *
4
+ * @param locale BCP 47 language tag of locale, e.g. `"es-ES"`.
5
+ * @param countryCode Two-letter country code (ISO 3166-1 alpha-2).
6
+ */
7
+ export declare const setDefaultPrefix: (locale: string, countryCode?: string) => string;
2
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/setDefaultPrefix/index.js"],"names":[],"mappings":"AAeO,yCAJI,MAAM,qBAEJ,MAAM,CAWlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/setDefaultPrefix/index.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,WAAY,MAAM,gBAAgB,MAAM,WAKpE,CAAC"}
@@ -1,2 +1,2 @@
1
- export { sortArrayByProperty } from "./sortArrayByProperty";
1
+ export { sortArrayByProperty } from './sortArrayByProperty';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/sortArrayByProperty/index.js"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/sortArrayByProperty/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1,2 +1,2 @@
1
- export function sortArrayByProperty(arrayToSort: any, property: any): any[];
1
+ export declare function sortArrayByProperty<T extends Record<PropertyKey, string>>(arrayToSort: T[], property: keyof T): T[];
2
2
  //# sourceMappingURL=sortArrayByProperty.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sortArrayByProperty.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.js"],"names":[],"mappings":"AACO,4EACkE"}
1
+ {"version":3,"file":"sortArrayByProperty.d.ts","sourceRoot":"","sources":["../../../../../src/phoneNumberInput/utils/sortArrayByProperty/sortArrayByProperty.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,EACvE,WAAW,EAAE,CAAC,EAAE,EAChB,QAAQ,EAAE,MAAM,CAAC,OAGlB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "46.6.0",
3
+ "version": "46.7.0",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -68,7 +68,6 @@
68
68
  "babel-plugin-formatjs": "^10.5.3",
69
69
  "babel-plugin-inline-react-svg": "^2.0.2",
70
70
  "enzyme": "^3.11.0",
71
- "html-loader": "^1.3.2",
72
71
  "jest": "^27.0.6",
73
72
  "jest-cli": "^27.0.6",
74
73
  "jest-fetch-mock": "^3.0.3",
@@ -78,12 +77,12 @@
78
77
  "rollup": "^3.28.1",
79
78
  "storybook": "^7.4.5",
80
79
  "@transferwise/less-config": "3.1.0",
81
- "@transferwise/neptune-css": "14.9.3",
80
+ "@transferwise/neptune-css": "14.9.4",
82
81
  "@wise/components-theming": "0.8.4"
83
82
  },
84
83
  "peerDependencies": {
85
84
  "@transferwise/icons": "^3.7.0",
86
- "@transferwise/neptune-css": "^14.9.3",
85
+ "@transferwise/neptune-css": "^14.9.4",
87
86
  "@wise/art": "^2.7.0",
88
87
  "@wise/components-theming": "^0.8.4",
89
88
  "react": ">=16.14",
@@ -24,8 +24,8 @@ describe('locale utils', () => {
24
24
  ['zh_HK', 'zh'],
25
25
  ['ja-JP', 'ja'],
26
26
  ['zhHK', null],
27
- [null, null],
28
- [undefined, null],
27
+ [null as any, null],
28
+ [undefined as any, null],
29
29
  ['', null],
30
30
  [' ', null],
31
31
  ['ar-dz', null],
@@ -51,8 +51,8 @@ describe('locale utils', () => {
51
51
  ['zh_HK', 'zh-HK'],
52
52
  ['ja-JP', 'ja-JP'],
53
53
  ['zhHK', null],
54
- [null, null],
55
- [undefined, null],
54
+ [null as any, null],
55
+ [undefined as any, null],
56
56
  ['', null],
57
57
  [' ', null],
58
58
  ['ar-dz', 'ar-DZ'],
@@ -0,0 +1,96 @@
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
+ }
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ export type {
15
15
  SelectInputTriggerButtonProps,
16
16
  } from './inputs/SelectInput';
17
17
  export type { TextAreaProps } from './inputs/TextArea';
18
+ export type { PhoneNumberInputProps } from './phoneNumberInput/PhoneNumberInput';
18
19
  export type { TextareaWithDisplayFormatProps } from './textareaWithDisplayFormat';
19
20
  export type { UploadedFile, UploadError, UploadResponse } from './uploadInput/types';
20
21
  export type { ModalProps } from './modal';
@@ -47,10 +47,6 @@
47
47
  padding-top: 0 !important;
48
48
  padding-bottom: 0 !important;
49
49
  }.np-form-control--size-sm {
50
- line-height: 1.5;
51
- line-height: var(--line-height-body);
52
- font-size: 1rem;
53
- font-size: var(--font-size-16);
54
50
  font-size: 0.875rem;
55
51
  font-size: var(--font-size-14);
56
52
  line-height: 155%;
@@ -158,10 +158,12 @@
158
158
  color: #5d7079;
159
159
  color: var(--color-content-secondary);
160
160
  }
161
- .np-select-input-placeholder {
161
+ .np-select-input-content {
162
162
  overflow: hidden;
163
163
  text-overflow: ellipsis;
164
164
  white-space: nowrap;
165
+ }
166
+ .np-select-input-placeholder {
165
167
  color: #768e9c;
166
168
  color: var(--color-content-tertiary);
167
169
  }
@@ -269,6 +271,9 @@
269
271
  padding: var(--size-12) var(--size-16);
270
272
  color: var(--color-interactive-primary);
271
273
  }
274
+ .np-select-input-option-container:focus {
275
+ outline: none;
276
+ }
272
277
  .np-select-input-option-container--active {
273
278
  box-shadow: inset 0 0 0 1px #c9cbce;
274
279
  box-shadow: inset 0 0 0 1px var(--color-interactive-secondary);
@@ -3,10 +3,13 @@
3
3
  @import "./_Popover.less";
4
4
  @import (reference) "../../node_modules/@transferwise/neptune-css/src/less/ring.less";
5
5
 
6
- .np-select-input-placeholder {
6
+ .np-select-input-content {
7
7
  overflow: hidden;
8
8
  text-overflow: ellipsis;
9
9
  white-space: nowrap;
10
+ }
11
+
12
+ .np-select-input-placeholder {
10
13
  color: var(--color-content-tertiary);
11
14
  }
12
15
 
@@ -100,6 +103,10 @@
100
103
  padding: var(--size-12) var(--size-16);
101
104
  color: var(--color-interactive-primary);
102
105
 
106
+ &:focus {
107
+ outline: none;
108
+ }
109
+
103
110
  &--active {
104
111
  box-shadow: inset 0 0 0 1px var(--color-interactive-secondary);
105
112
  }
@@ -182,4 +182,30 @@ describe('SelectInput', () => {
182
182
  const listbox = screen.getByRole('listbox');
183
183
  expect(within(listbox).getAllByRole('option')).toHaveLength(2);
184
184
  });
185
+
186
+ it('selects multiple options', async () => {
187
+ render(
188
+ <SelectInput
189
+ multiple
190
+ items={[
191
+ { type: 'option', value: 'USD' },
192
+ { type: 'option', value: 'EUR' },
193
+ ]}
194
+ />,
195
+ );
196
+
197
+ const trigger = screen.getAllByRole('button')[0];
198
+ // eslint-disable-next-line @typescript-eslint/require-await
199
+ await act(async () => {
200
+ userEvent.click(trigger);
201
+ });
202
+
203
+ const listbox = screen.getByRole('listbox');
204
+ const options = within(listbox).getAllByRole('option');
205
+ options.forEach((option) => {
206
+ userEvent.click(option);
207
+ });
208
+
209
+ expect(trigger).toHaveTextContent('USD, EUR');
210
+ });
185
211
  });
@@ -242,7 +242,7 @@ export const Currencies: StoryObj<{
242
242
  onChange: (value: Currency) => void;
243
243
  }> = {
244
244
  render: function Story({ onChange }) {
245
- const [selectedCurrency, setSelectedCurrency] = useState<Currency>(popularCurrencies[0]);
245
+ const [selectedCurrency, setSelectedCurrency] = useState(popularCurrencies[0]);
246
246
 
247
247
  return (
248
248
  <SelectInput
@@ -301,6 +301,78 @@ export const Currencies: StoryObj<{
301
301
  },
302
302
  };
303
303
 
304
+ export const MultipleCurrencies: StoryObj<{
305
+ onChange: (value: Currency[]) => void;
306
+ }> = {
307
+ render: function Story({ onChange }) {
308
+ const [selectedCurrencies, setSelectedCurrencies] = useState<readonly Currency[]>([
309
+ popularCurrencies[0],
310
+ ]);
311
+
312
+ return (
313
+ <SelectInput
314
+ multiple
315
+ placeholder="Choose currencies…"
316
+ items={[
317
+ {
318
+ type: 'group',
319
+ label: 'Popular currencies',
320
+ options: popularCurrencies.map((currency) => currencyOption(currency)),
321
+ },
322
+ {
323
+ type: 'group',
324
+ label: 'All currencies',
325
+ options: allCurrencies.map((currency) => currencyOption(currency)),
326
+ },
327
+ ]}
328
+ value={selectedCurrencies}
329
+ renderValue={(currency, withinTrigger) =>
330
+ withinTrigger ? (
331
+ currency.code
332
+ ) : (
333
+ <SelectInputOptionContent
334
+ title={currency.code}
335
+ note={currency.name}
336
+ icon={<Flag code={currency.code} intrinsicSize={24} />}
337
+ />
338
+ )
339
+ }
340
+ // eslint-disable-next-line sonarjs/no-identical-functions
341
+ renderFooter={({ resultsEmpty, queryNormalized: normalizedQuery }) =>
342
+ resultsEmpty && normalizedQuery != null && /^[a-z]{3}$/u.test(normalizedQuery) ? (
343
+ <>
344
+ It’s not possible use {normalizedQuery.toUpperCase()} yet.{' '}
345
+ <a href="#_" className="np-text-link-default">
346
+ Email me when it’s available.
347
+ </a>
348
+ </>
349
+ ) : (
350
+ <>
351
+ Can’t find it?{' '}
352
+ <a href="#_" className="np-text-link-default">
353
+ Request the currency you need,
354
+ </a>{' '}
355
+ and we’ll notify you once it’s available.
356
+ </>
357
+ )
358
+ }
359
+ filterable
360
+ filterPlaceholder="Type a currency / country"
361
+ size="lg"
362
+ onChange={(currency) => {
363
+ setSelectedCurrencies(currency);
364
+ onChange(currency);
365
+ }}
366
+ />
367
+ );
368
+ },
369
+ argTypes: {
370
+ onChange: {
371
+ action: 'changed',
372
+ },
373
+ },
374
+ };
375
+
304
376
  export const CustomTrigger: StoryObj = {
305
377
  render: function Story() {
306
378
  return (