@transferwise/components 0.0.0-experimental-9442a3d → 0.0.0-experimental-fe42ce4

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 (120) hide show
  1. package/build/dateInput/DateInput.js +2 -2
  2. package/build/dateInput/DateInput.js.map +1 -1
  3. package/build/dateInput/DateInput.mjs +2 -2
  4. package/build/dateInput/DateInput.mjs.map +1 -1
  5. package/build/i18n/en.json +2 -0
  6. package/build/i18n/en.json.js +2 -0
  7. package/build/i18n/en.json.js.map +1 -1
  8. package/build/i18n/en.json.mjs +2 -0
  9. package/build/i18n/en.json.mjs.map +1 -1
  10. package/build/index.js +2 -0
  11. package/build/index.js.map +1 -1
  12. package/build/index.mjs +1 -0
  13. package/build/index.mjs.map +1 -1
  14. package/build/main.css +66 -0
  15. package/build/moneyInputField/AmountInput.js +284 -0
  16. package/build/moneyInputField/AmountInput.js.map +1 -0
  17. package/build/moneyInputField/AmountInput.mjs +282 -0
  18. package/build/moneyInputField/AmountInput.mjs.map +1 -0
  19. package/build/moneyInputField/AnimatedNumber.js +50 -0
  20. package/build/moneyInputField/AnimatedNumber.js.map +1 -0
  21. package/build/moneyInputField/AnimatedNumber.mjs +48 -0
  22. package/build/moneyInputField/AnimatedNumber.mjs.map +1 -0
  23. package/build/moneyInputField/Chevron.js +33 -0
  24. package/build/moneyInputField/Chevron.js.map +1 -0
  25. package/build/moneyInputField/Chevron.mjs +31 -0
  26. package/build/moneyInputField/Chevron.mjs.map +1 -0
  27. package/build/moneyInputField/CurrencySelector.js +160 -0
  28. package/build/moneyInputField/CurrencySelector.js.map +1 -0
  29. package/build/moneyInputField/CurrencySelector.mjs +157 -0
  30. package/build/moneyInputField/CurrencySelector.mjs.map +1 -0
  31. package/build/moneyInputField/MoneyInputField.js +112 -0
  32. package/build/moneyInputField/MoneyInputField.js.map +1 -0
  33. package/build/moneyInputField/MoneyInputField.messages.js +17 -0
  34. package/build/moneyInputField/MoneyInputField.messages.js.map +1 -0
  35. package/build/moneyInputField/MoneyInputField.messages.mjs +13 -0
  36. package/build/moneyInputField/MoneyInputField.messages.mjs.map +1 -0
  37. package/build/moneyInputField/MoneyInputField.mjs +108 -0
  38. package/build/moneyInputField/MoneyInputField.mjs.map +1 -0
  39. package/build/moneyInputField/useFocus.js +37 -0
  40. package/build/moneyInputField/useFocus.js.map +1 -0
  41. package/build/moneyInputField/useFocus.mjs +35 -0
  42. package/build/moneyInputField/useFocus.mjs.map +1 -0
  43. package/build/moneyInputField/useInputStyle.js +71 -0
  44. package/build/moneyInputField/useInputStyle.js.map +1 -0
  45. package/build/moneyInputField/useInputStyle.mjs +69 -0
  46. package/build/moneyInputField/useInputStyle.mjs.map +1 -0
  47. package/build/moneyInputField/utils.js +87 -0
  48. package/build/moneyInputField/utils.js.map +1 -0
  49. package/build/moneyInputField/utils.mjs +78 -0
  50. package/build/moneyInputField/utils.mjs.map +1 -0
  51. package/build/phoneNumberInput/PhoneNumberInput.js +1 -1
  52. package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
  53. package/build/phoneNumberInput/PhoneNumberInput.mjs +1 -1
  54. package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  55. package/build/styles/inputs/Input.css +5 -0
  56. package/build/styles/inputs/TextArea.css +5 -0
  57. package/build/styles/main.css +66 -0
  58. package/build/styles/moneyInputField/AmountInput.css +32 -0
  59. package/build/styles/moneyInputField/Chevron.css +12 -0
  60. package/build/styles/moneyInputField/CurrencySelector.css +6 -0
  61. package/build/styles/moneyInputField/MoneyInputField.css +61 -0
  62. package/build/types/index.d.ts +2 -0
  63. package/build/types/index.d.ts.map +1 -1
  64. package/build/types/moneyInputField/AmountInput.d.ts +13 -0
  65. package/build/types/moneyInputField/AmountInput.d.ts.map +1 -0
  66. package/build/types/moneyInputField/AnimatedNumber.d.ts +9 -0
  67. package/build/types/moneyInputField/AnimatedNumber.d.ts.map +1 -0
  68. package/build/types/moneyInputField/Chevron.d.ts +6 -0
  69. package/build/types/moneyInputField/Chevron.d.ts.map +1 -0
  70. package/build/types/moneyInputField/CurrencySelector.d.ts +30 -0
  71. package/build/types/moneyInputField/CurrencySelector.d.ts.map +1 -0
  72. package/build/types/moneyInputField/MoneyInputField.d.ts +22 -0
  73. package/build/types/moneyInputField/MoneyInputField.d.ts.map +1 -0
  74. package/build/types/moneyInputField/MoneyInputField.messages.d.ts +12 -0
  75. package/build/types/moneyInputField/MoneyInputField.messages.d.ts.map +1 -0
  76. package/build/types/moneyInputField/index.d.ts +3 -0
  77. package/build/types/moneyInputField/index.d.ts.map +1 -0
  78. package/build/types/moneyInputField/useFocus.d.ts +7 -0
  79. package/build/types/moneyInputField/useFocus.d.ts.map +1 -0
  80. package/build/types/moneyInputField/useInputStyle.d.ts +10 -0
  81. package/build/types/moneyInputField/useInputStyle.d.ts.map +1 -0
  82. package/build/types/moneyInputField/useSelectionRange.d.ts +10 -0
  83. package/build/types/moneyInputField/useSelectionRange.d.ts.map +1 -0
  84. package/build/types/moneyInputField/utils.d.ts +22 -0
  85. package/build/types/moneyInputField/utils.d.ts.map +1 -0
  86. package/build/types/test-utils/index.d.ts +4 -0
  87. package/build/types/test-utils/index.d.ts.map +1 -1
  88. package/package.json +3 -2
  89. package/src/DisabledComponents.story.tsx +156 -0
  90. package/src/dateInput/DateInput.tsx +2 -2
  91. package/src/i18n/en.json +2 -0
  92. package/src/index.ts +2 -0
  93. package/src/inputs/Input.css +5 -0
  94. package/src/inputs/TextArea.css +5 -0
  95. package/src/inputs/_common.less +5 -0
  96. package/src/main.css +66 -0
  97. package/src/main.less +1 -0
  98. package/src/moneyInputField/AmountInput.css +32 -0
  99. package/src/moneyInputField/AmountInput.less +43 -0
  100. package/src/moneyInputField/AmountInput.tsx +355 -0
  101. package/src/moneyInputField/AnimatedNumber.tsx +40 -0
  102. package/src/moneyInputField/Chevron.css +12 -0
  103. package/src/moneyInputField/Chevron.less +13 -0
  104. package/src/moneyInputField/Chevron.tsx +35 -0
  105. package/src/moneyInputField/CurrencySelector.css +6 -0
  106. package/src/moneyInputField/CurrencySelector.less +7 -0
  107. package/src/moneyInputField/CurrencySelector.tsx +219 -0
  108. package/src/moneyInputField/MoneyInputField.css +61 -0
  109. package/src/moneyInputField/MoneyInputField.less +16 -0
  110. package/src/moneyInputField/MoneyInputField.messages.ts +13 -0
  111. package/src/moneyInputField/MoneyInputField.story.tsx +193 -0
  112. package/src/moneyInputField/MoneyInputField.tsx +118 -0
  113. package/src/moneyInputField/index.ts +2 -0
  114. package/src/moneyInputField/useFocus.ts +35 -0
  115. package/src/moneyInputField/useInputStyle.ts +85 -0
  116. package/src/moneyInputField/useSelectionRange.ts +23 -0
  117. package/src/moneyInputField/utils.spec.ts +114 -0
  118. package/src/moneyInputField/utils.ts +116 -0
  119. package/src/phoneNumberInput/PhoneNumberInput.tsx +1 -1
  120. 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
+ };
@@ -245,7 +245,7 @@ const PhoneNumberInput = ({
245
245
  {formatMessage(messages.phoneNumberLabel)}
246
246
  </label>
247
247
  <div className="tw-telephone__number-input">
248
- <div className={`input-group input-group-${size}`}>
248
+ <div className={`input-group input-group-${size} ${disabled ? 'disabled' : ''}`}>
249
249
  <Input
250
250
  ref={phoneNumberInputRef}
251
251
  id={ids.phoneNumber.input}
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: [],