@transferwise/components 0.0.0-experimental-89ae24f → 0.0.0-experimental-c42d7d6

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 (104) hide show
  1. package/build/i18n/en.json +2 -0
  2. package/build/i18n/en.json.js +2 -0
  3. package/build/i18n/en.json.js.map +1 -1
  4. package/build/i18n/en.json.mjs +2 -0
  5. package/build/i18n/en.json.mjs.map +1 -1
  6. package/build/index.js +2 -0
  7. package/build/index.js.map +1 -1
  8. package/build/index.mjs +1 -0
  9. package/build/index.mjs.map +1 -1
  10. package/build/main.css +58 -0
  11. package/build/moneyInputField/AmountInput.js +281 -0
  12. package/build/moneyInputField/AmountInput.js.map +1 -0
  13. package/build/moneyInputField/AmountInput.mjs +279 -0
  14. package/build/moneyInputField/AmountInput.mjs.map +1 -0
  15. package/build/moneyInputField/AnimatedNumber.js +50 -0
  16. package/build/moneyInputField/AnimatedNumber.js.map +1 -0
  17. package/build/moneyInputField/AnimatedNumber.mjs +48 -0
  18. package/build/moneyInputField/AnimatedNumber.mjs.map +1 -0
  19. package/build/moneyInputField/Chevron.js +33 -0
  20. package/build/moneyInputField/Chevron.js.map +1 -0
  21. package/build/moneyInputField/Chevron.mjs +31 -0
  22. package/build/moneyInputField/Chevron.mjs.map +1 -0
  23. package/build/moneyInputField/CurrencySelector.js +160 -0
  24. package/build/moneyInputField/CurrencySelector.js.map +1 -0
  25. package/build/moneyInputField/CurrencySelector.mjs +157 -0
  26. package/build/moneyInputField/CurrencySelector.mjs.map +1 -0
  27. package/build/moneyInputField/MoneyInputField.js +113 -0
  28. package/build/moneyInputField/MoneyInputField.js.map +1 -0
  29. package/build/moneyInputField/MoneyInputField.messages.js +17 -0
  30. package/build/moneyInputField/MoneyInputField.messages.js.map +1 -0
  31. package/build/moneyInputField/MoneyInputField.messages.mjs +13 -0
  32. package/build/moneyInputField/MoneyInputField.messages.mjs.map +1 -0
  33. package/build/moneyInputField/MoneyInputField.mjs +109 -0
  34. package/build/moneyInputField/MoneyInputField.mjs.map +1 -0
  35. package/build/moneyInputField/useFocus.js +37 -0
  36. package/build/moneyInputField/useFocus.js.map +1 -0
  37. package/build/moneyInputField/useFocus.mjs +35 -0
  38. package/build/moneyInputField/useFocus.mjs.map +1 -0
  39. package/build/moneyInputField/useInputStyle.js +71 -0
  40. package/build/moneyInputField/useInputStyle.js.map +1 -0
  41. package/build/moneyInputField/useInputStyle.mjs +69 -0
  42. package/build/moneyInputField/useInputStyle.mjs.map +1 -0
  43. package/build/moneyInputField/utils.js +87 -0
  44. package/build/moneyInputField/utils.js.map +1 -0
  45. package/build/moneyInputField/utils.mjs +78 -0
  46. package/build/moneyInputField/utils.mjs.map +1 -0
  47. package/build/styles/main.css +58 -0
  48. package/build/styles/moneyInputField/AmountInput.css +32 -0
  49. package/build/styles/moneyInputField/Chevron.css +12 -0
  50. package/build/styles/moneyInputField/CurrencySelector.css +6 -0
  51. package/build/styles/moneyInputField/MoneyInputField.css +58 -0
  52. package/build/types/index.d.ts +2 -0
  53. package/build/types/index.d.ts.map +1 -1
  54. package/build/types/moneyInputField/AmountInput.d.ts +13 -0
  55. package/build/types/moneyInputField/AmountInput.d.ts.map +1 -0
  56. package/build/types/moneyInputField/AnimatedNumber.d.ts +9 -0
  57. package/build/types/moneyInputField/AnimatedNumber.d.ts.map +1 -0
  58. package/build/types/moneyInputField/Chevron.d.ts +6 -0
  59. package/build/types/moneyInputField/Chevron.d.ts.map +1 -0
  60. package/build/types/moneyInputField/CurrencySelector.d.ts +30 -0
  61. package/build/types/moneyInputField/CurrencySelector.d.ts.map +1 -0
  62. package/build/types/moneyInputField/MoneyInputField.d.ts +30 -0
  63. package/build/types/moneyInputField/MoneyInputField.d.ts.map +1 -0
  64. package/build/types/moneyInputField/MoneyInputField.messages.d.ts +12 -0
  65. package/build/types/moneyInputField/MoneyInputField.messages.d.ts.map +1 -0
  66. package/build/types/moneyInputField/index.d.ts +3 -0
  67. package/build/types/moneyInputField/index.d.ts.map +1 -0
  68. package/build/types/moneyInputField/useFocus.d.ts +7 -0
  69. package/build/types/moneyInputField/useFocus.d.ts.map +1 -0
  70. package/build/types/moneyInputField/useInputStyle.d.ts +10 -0
  71. package/build/types/moneyInputField/useInputStyle.d.ts.map +1 -0
  72. package/build/types/moneyInputField/useSelectionRange.d.ts +10 -0
  73. package/build/types/moneyInputField/useSelectionRange.d.ts.map +1 -0
  74. package/build/types/moneyInputField/utils.d.ts +22 -0
  75. package/build/types/moneyInputField/utils.d.ts.map +1 -0
  76. package/build/types/test-utils/index.d.ts +4 -0
  77. package/build/types/test-utils/index.d.ts.map +1 -1
  78. package/package.json +9 -2
  79. package/src/i18n/en.json +2 -0
  80. package/src/index.ts +2 -0
  81. package/src/main.css +58 -0
  82. package/src/main.less +1 -0
  83. package/src/moneyInputField/AmountInput.css +32 -0
  84. package/src/moneyInputField/AmountInput.less +43 -0
  85. package/src/moneyInputField/AmountInput.tsx +353 -0
  86. package/src/moneyInputField/AnimatedNumber.tsx +40 -0
  87. package/src/moneyInputField/Chevron.css +12 -0
  88. package/src/moneyInputField/Chevron.less +13 -0
  89. package/src/moneyInputField/Chevron.tsx +35 -0
  90. package/src/moneyInputField/CurrencySelector.css +6 -0
  91. package/src/moneyInputField/CurrencySelector.less +7 -0
  92. package/src/moneyInputField/CurrencySelector.tsx +218 -0
  93. package/src/moneyInputField/MoneyInputField.css +58 -0
  94. package/src/moneyInputField/MoneyInputField.less +13 -0
  95. package/src/moneyInputField/MoneyInputField.messages.ts +13 -0
  96. package/src/moneyInputField/MoneyInputField.story.tsx +188 -0
  97. package/src/moneyInputField/MoneyInputField.tsx +124 -0
  98. package/src/moneyInputField/index.ts +2 -0
  99. package/src/moneyInputField/useFocus.ts +35 -0
  100. package/src/moneyInputField/useInputStyle.ts +85 -0
  101. package/src/moneyInputField/useSelectionRange.ts +23 -0
  102. package/src/moneyInputField/utils.spec.ts +114 -0
  103. package/src/moneyInputField/utils.ts +116 -0
  104. package/src/ssr.spec.tsx +1 -0
@@ -0,0 +1,116 @@
1
+ import { formatAmount } from '@transferwise/formatting';
2
+ import type { KeyboardEvent } from 'react';
3
+
4
+ export const getDecimalSeparator = (currency: string, locale: string): string | null => {
5
+ return formatAmount(1.1, currency, locale).replace(/\p{Number}/gu, '');
6
+ };
7
+
8
+ export const getGroupSeparator = (currency: string, locale: string): string | null => {
9
+ return formatAmount(10000000, currency, locale).replace(/\p{Number}/gu, '')[0];
10
+ };
11
+
12
+ export const getDecimalCount = (currency: string, locale: string): number => {
13
+ const decimalSeparator = getDecimalSeparator(currency, locale);
14
+ if (!decimalSeparator) {
15
+ return 0;
16
+ }
17
+ const parts = formatAmount(1.1, currency, locale).split(decimalSeparator);
18
+ return parts.length === 2 ? parts[1].length : 0;
19
+ };
20
+
21
+ export const getEnteredDecimalsCount = (value: string, decimalSeparator: string) => {
22
+ return value.split(decimalSeparator)[1]?.length ?? 0;
23
+ };
24
+
25
+ export const getUnformattedNumber = ({
26
+ value: formattedValue,
27
+ currency,
28
+ locale,
29
+ }: {
30
+ value: string;
31
+ currency: string;
32
+ locale: string;
33
+ }): number | null => {
34
+ const groupSeparator = getGroupSeparator(currency, locale);
35
+ const decimalSeparator = getDecimalSeparator(currency, locale);
36
+ if (!formattedValue) {
37
+ return null;
38
+ }
39
+
40
+ // parseFloat can't handle thousands separators
41
+ const withoutGroupSeparator = groupSeparator
42
+ ? formattedValue.replace(/ /gu, '').replace(new RegExp(`\\${groupSeparator}`, 'g'), '')
43
+ : formattedValue;
44
+
45
+ // parseFloat can only handle . as decimal separator
46
+ const withNormalisedDecimalSeparator = decimalSeparator
47
+ ? withoutGroupSeparator.replace(decimalSeparator, '.')
48
+ : withoutGroupSeparator;
49
+
50
+ const parsedValue = Number.parseFloat(withNormalisedDecimalSeparator);
51
+ return parsedValue;
52
+ };
53
+
54
+ export const getFormattedString = ({
55
+ value: unformattedValue,
56
+ currency,
57
+ locale,
58
+ alwaysShowDecimals = false,
59
+ }: {
60
+ value: number;
61
+ currency: string;
62
+ locale: string;
63
+ alwaysShowDecimals?: boolean;
64
+ }): string => {
65
+ const decimalSeparator = getDecimalSeparator(currency, locale);
66
+ // formatAmount rounds extra decimals, so 1.999 will become 2. Instead we will manually strip extra decimals so that it becomes 1.99 after formatting
67
+ const decimalCount = getDecimalCount(currency, locale);
68
+ const unformattedString = unformattedValue.toString();
69
+
70
+ const [integerPart, decimalPart] = decimalSeparator
71
+ ? unformattedString.split(decimalSeparator)
72
+ : [unformattedString, undefined];
73
+
74
+ const formattedDecimalPart = decimalPart ? decimalPart.slice(0, decimalCount) : '';
75
+
76
+ const sanitisedUnformattedValue = Number.parseFloat(`${integerPart}.${formattedDecimalPart}`);
77
+
78
+ return formatAmount(sanitisedUnformattedValue, currency, locale, {
79
+ alwaysShowDecimals,
80
+ });
81
+ };
82
+
83
+ export const isInputPossiblyOverflowing = ({
84
+ ref,
85
+ value,
86
+ }: {
87
+ ref: React.RefObject<HTMLInputElement>;
88
+ value: string;
89
+ }) => {
90
+ const textLength = value.length;
91
+ const inputWidth = ref.current?.clientWidth;
92
+ if (!inputWidth || !textLength) {
93
+ return;
94
+ }
95
+
96
+ const maxCharactersWithoutOverflow = Math.floor(inputWidth / 19);
97
+ return textLength > maxCharactersWithoutOverflow;
98
+ };
99
+
100
+ const allowedInputKeys = new Set([
101
+ 'Backspace',
102
+ 'Delete',
103
+ ',',
104
+ '.',
105
+ 'ArrowLeft',
106
+ 'ArrowRight',
107
+ 'Enter',
108
+ 'Tab',
109
+ ]);
110
+
111
+ export const isAllowedInputKey = (e: KeyboardEvent<HTMLInputElement>) => {
112
+ const { metaKey, key, ctrlKey } = e;
113
+ const isNumberKey = !Number.isNaN(Number.parseInt(key, 10));
114
+
115
+ return isNumberKey || metaKey || ctrlKey || allowedInputKeys.has(key);
116
+ };
package/src/ssr.spec.tsx CHANGED
@@ -92,6 +92,7 @@ describe('Server side rendering', () => {
92
92
  // stick all possible properties we might need to render all components in here
93
93
  const allProps: Record<string, unknown> = {
94
94
  currencies: [],
95
+ currencySelector: { options: [] },
95
96
  steps: [],
96
97
  stepper: {
97
98
  steps: [],