@transferwise/components 0.0.0-experimental-4ed3f9f → 0.0.0-experimental-643f4d2
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/en.json +0 -2
- package/build/i18n/en.json.js +0 -2
- package/build/i18n/en.json.js.map +1 -1
- package/build/i18n/en.json.mjs +0 -2
- package/build/i18n/en.json.mjs.map +1 -1
- package/build/index.js +0 -2
- package/build/index.js.map +1 -1
- package/build/index.mjs +0 -1
- package/build/index.mjs.map +1 -1
- package/build/main.css +15 -65
- package/build/prompt/InlinePrompt/InlinePrompt.js +0 -7
- package/build/prompt/InlinePrompt/InlinePrompt.js.map +1 -1
- package/build/prompt/InlinePrompt/InlinePrompt.mjs +1 -8
- package/build/prompt/InlinePrompt/InlinePrompt.mjs.map +1 -1
- package/build/styles/main.css +15 -65
- package/build/styles/moneyInput/MoneyInput.css +8 -0
- package/build/styles/prompt/InlinePrompt/InlinePrompt.css +7 -7
- package/build/types/index.d.ts +0 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/prompt/InlinePrompt/InlinePrompt.d.ts +2 -3
- package/build/types/prompt/InlinePrompt/InlinePrompt.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts +0 -4
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/i18n/en.json +0 -2
- package/src/index.ts +0 -2
- package/src/main.css +15 -65
- package/src/main.less +0 -1
- package/src/moneyInput/MoneyInput.css +8 -0
- package/src/moneyInput/MoneyInput.less +5 -0
- package/src/prompt/InlinePrompt/InlinePrompt.css +7 -7
- package/src/prompt/InlinePrompt/InlinePrompt.less +7 -7
- package/src/prompt/InlinePrompt/InlinePrompt.spec.tsx +0 -6
- package/src/prompt/InlinePrompt/InlinePrompt.tsx +2 -12
- package/src/ssr.spec.tsx +0 -1
- package/build/expressiveMoneyInput/AmountInput.js +0 -281
- package/build/expressiveMoneyInput/AmountInput.js.map +0 -1
- package/build/expressiveMoneyInput/AmountInput.mjs +0 -279
- package/build/expressiveMoneyInput/AmountInput.mjs.map +0 -1
- package/build/expressiveMoneyInput/AnimatedNumber.js +0 -50
- package/build/expressiveMoneyInput/AnimatedNumber.js.map +0 -1
- package/build/expressiveMoneyInput/AnimatedNumber.mjs +0 -48
- package/build/expressiveMoneyInput/AnimatedNumber.mjs.map +0 -1
- package/build/expressiveMoneyInput/Chevron.js +0 -31
- package/build/expressiveMoneyInput/Chevron.js.map +0 -1
- package/build/expressiveMoneyInput/Chevron.mjs +0 -29
- package/build/expressiveMoneyInput/Chevron.mjs.map +0 -1
- package/build/expressiveMoneyInput/CurrencySelector.js +0 -160
- package/build/expressiveMoneyInput/CurrencySelector.js.map +0 -1
- package/build/expressiveMoneyInput/CurrencySelector.mjs +0 -157
- package/build/expressiveMoneyInput/CurrencySelector.mjs.map +0 -1
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.js +0 -114
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.js.map +0 -1
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.messages.js +0 -17
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.messages.js.map +0 -1
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.messages.mjs +0 -13
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.messages.mjs.map +0 -1
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.mjs +0 -110
- package/build/expressiveMoneyInput/ExpressiveMoneyInput.mjs.map +0 -1
- package/build/expressiveMoneyInput/useFocus.js +0 -37
- package/build/expressiveMoneyInput/useFocus.js.map +0 -1
- package/build/expressiveMoneyInput/useFocus.mjs +0 -35
- package/build/expressiveMoneyInput/useFocus.mjs.map +0 -1
- package/build/expressiveMoneyInput/useInputStyle.js +0 -71
- package/build/expressiveMoneyInput/useInputStyle.js.map +0 -1
- package/build/expressiveMoneyInput/useInputStyle.mjs +0 -69
- package/build/expressiveMoneyInput/useInputStyle.mjs.map +0 -1
- package/build/expressiveMoneyInput/utils.js +0 -87
- package/build/expressiveMoneyInput/utils.js.map +0 -1
- package/build/expressiveMoneyInput/utils.mjs +0 -78
- package/build/expressiveMoneyInput/utils.mjs.map +0 -1
- package/build/styles/expressiveMoneyInput/AmountInput.css +0 -32
- package/build/styles/expressiveMoneyInput/Chevron.css +0 -12
- package/build/styles/expressiveMoneyInput/CurrencySelector.css +0 -6
- package/build/styles/expressiveMoneyInput/ExpressiveMoneyInput.css +0 -58
- package/build/types/expressiveMoneyInput/AmountInput.d.ts +0 -13
- package/build/types/expressiveMoneyInput/AmountInput.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/AnimatedNumber.d.ts +0 -9
- package/build/types/expressiveMoneyInput/AnimatedNumber.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/Chevron.d.ts +0 -6
- package/build/types/expressiveMoneyInput/Chevron.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/CurrencySelector.d.ts +0 -30
- package/build/types/expressiveMoneyInput/CurrencySelector.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/ExpressiveMoneyInput.d.ts +0 -33
- package/build/types/expressiveMoneyInput/ExpressiveMoneyInput.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/ExpressiveMoneyInput.messages.d.ts +0 -12
- package/build/types/expressiveMoneyInput/ExpressiveMoneyInput.messages.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/index.d.ts +0 -3
- package/build/types/expressiveMoneyInput/index.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/useFocus.d.ts +0 -7
- package/build/types/expressiveMoneyInput/useFocus.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/useInputStyle.d.ts +0 -10
- package/build/types/expressiveMoneyInput/useInputStyle.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/useSelectionRange.d.ts +0 -10
- package/build/types/expressiveMoneyInput/useSelectionRange.d.ts.map +0 -1
- package/build/types/expressiveMoneyInput/utils.d.ts +0 -22
- package/build/types/expressiveMoneyInput/utils.d.ts.map +0 -1
- package/src/expressiveMoneyInput/AmountInput.css +0 -32
- package/src/expressiveMoneyInput/AmountInput.less +0 -43
- package/src/expressiveMoneyInput/AmountInput.tsx +0 -353
- package/src/expressiveMoneyInput/AnimatedNumber.tsx +0 -40
- package/src/expressiveMoneyInput/Chevron.css +0 -12
- package/src/expressiveMoneyInput/Chevron.less +0 -13
- package/src/expressiveMoneyInput/Chevron.tsx +0 -35
- package/src/expressiveMoneyInput/CurrencySelector.css +0 -6
- package/src/expressiveMoneyInput/CurrencySelector.less +0 -7
- package/src/expressiveMoneyInput/CurrencySelector.tsx +0 -218
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.css +0 -58
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.less +0 -13
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.messages.ts +0 -13
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.story.tsx +0 -290
- package/src/expressiveMoneyInput/ExpressiveMoneyInput.tsx +0 -118
- package/src/expressiveMoneyInput/index.ts +0 -2
- package/src/expressiveMoneyInput/useFocus.ts +0 -35
- package/src/expressiveMoneyInput/useInputStyle.ts +0 -85
- package/src/expressiveMoneyInput/useSelectionRange.ts +0 -23
- package/src/expressiveMoneyInput/utils.spec.ts +0 -114
- package/src/expressiveMoneyInput/utils.ts +0 -116
- package/src/prompt/InlinePrompt/InlinePrompt.story.tsx +0 -57
package/src/main.css
CHANGED
|
@@ -526,26 +526,26 @@
|
|
|
526
526
|
background-color: var(--color-sentiment-positive-secondary-active);
|
|
527
527
|
}
|
|
528
528
|
.wds-inline-prompt--proposition {
|
|
529
|
-
background-color:
|
|
530
|
-
color: var(--color-
|
|
529
|
+
background-color: var(--color-sentiment-positive-secondary);
|
|
530
|
+
color: var(--color-sentiment-positive-primary);
|
|
531
531
|
}
|
|
532
532
|
.wds-inline-prompt--proposition a,
|
|
533
533
|
.wds-inline-prompt--proposition button {
|
|
534
|
-
color: var(--color-
|
|
534
|
+
color: var(--color-sentiment-positive-primary);
|
|
535
535
|
}
|
|
536
536
|
.wds-inline-prompt--proposition a:hover,
|
|
537
537
|
.wds-inline-prompt--proposition button:hover {
|
|
538
|
-
color: var(--color-
|
|
538
|
+
color: var(--color-sentiment-positive-primary-hover);
|
|
539
539
|
}
|
|
540
540
|
.wds-inline-prompt--proposition a:active,
|
|
541
541
|
.wds-inline-prompt--proposition button:active {
|
|
542
|
-
color: var(--color-
|
|
542
|
+
color: var(--color-sentiment-positive-primary-active);
|
|
543
543
|
}
|
|
544
544
|
.wds-inline-prompt.wds-inline-prompt--proposition:has(a, button):hover {
|
|
545
|
-
background-color:
|
|
545
|
+
background-color: var(--color-sentiment-positive-secondary-hover);
|
|
546
546
|
}
|
|
547
547
|
.wds-inline-prompt.wds-inline-prompt--proposition:has(a, button):active {
|
|
548
|
-
background-color:
|
|
548
|
+
background-color: var(--color-sentiment-positive-secondary-active);
|
|
549
549
|
}
|
|
550
550
|
.wds-inline-prompt--neutral {
|
|
551
551
|
background-color: rgba(134,167,189,0.10196);
|
|
@@ -4421,6 +4421,14 @@ button.np-link {
|
|
|
4421
4421
|
flex-shrink: 0;
|
|
4422
4422
|
width: auto;
|
|
4423
4423
|
}
|
|
4424
|
+
.tw-money-input .input-group-addon:not(.amount-currency-select-btn):not(.tw-money-input__fixed-currency):not(:has(~ .tw-money-input__fixed-currency)) {
|
|
4425
|
+
padding-right: 0 !important;
|
|
4426
|
+
}
|
|
4427
|
+
[dir="rtl"] .tw-money-input .input-group-addon:not(.amount-currency-select-btn):not(.tw-money-input__fixed-currency):not(:has(~ .tw-money-input__fixed-currency)) {
|
|
4428
|
+
padding-left: 0 !important;
|
|
4429
|
+
padding-right: 0 !important;
|
|
4430
|
+
padding-right: initial !important;
|
|
4431
|
+
}
|
|
4424
4432
|
.tw-money-input .amount-currency-select-btn {
|
|
4425
4433
|
flex-shrink: 0;
|
|
4426
4434
|
width: auto;
|
|
@@ -4447,64 +4455,6 @@ button.np-link {
|
|
|
4447
4455
|
box-shadow: inset 0 0 0 1px #c9cbce !important;
|
|
4448
4456
|
box-shadow: inset 0 0 0 1px var(--color-interactive-secondary) !important;
|
|
4449
4457
|
}
|
|
4450
|
-
.wds-amount-input-container {
|
|
4451
|
-
width: 100%;
|
|
4452
|
-
}
|
|
4453
|
-
.wds-amount-input-input-container {
|
|
4454
|
-
display: flex;
|
|
4455
|
-
justify-content: right;
|
|
4456
|
-
width: 100%;
|
|
4457
|
-
transition: font-size 0.4s cubic-bezier(0.3, 0, 0.1, 1), height 0.4s cubic-bezier(0.3, 0, 0.1, 1), margin-top 0.4s cubic-bezier(0.3, 0, 0.1, 1), color 0.4s ease;
|
|
4458
|
-
color: var(--color-interactive-primary);
|
|
4459
|
-
overflow: hidden;
|
|
4460
|
-
margin-bottom: 0 !important;
|
|
4461
|
-
}
|
|
4462
|
-
@media (prefers-reduced-motion: reduce) {
|
|
4463
|
-
.wds-amount-input-input-container {
|
|
4464
|
-
transition: none;
|
|
4465
|
-
}
|
|
4466
|
-
}
|
|
4467
|
-
.wds-amount-input-input {
|
|
4468
|
-
border: none;
|
|
4469
|
-
outline: none;
|
|
4470
|
-
flex-grow: 1;
|
|
4471
|
-
text-align: right;
|
|
4472
|
-
background-color: transparent;
|
|
4473
|
-
}
|
|
4474
|
-
.wds-amount-input-input:focus-visible {
|
|
4475
|
-
outline: none;
|
|
4476
|
-
}
|
|
4477
|
-
.wds-amount-input-placeholder {
|
|
4478
|
-
flex-grow: 0;
|
|
4479
|
-
display: flex;
|
|
4480
|
-
align-items: center;
|
|
4481
|
-
}
|
|
4482
|
-
.wds-currency-selector:disabled {
|
|
4483
|
-
opacity: 1 !important;
|
|
4484
|
-
cursor: auto !important;
|
|
4485
|
-
cursor: initial !important;
|
|
4486
|
-
mix-blend-mode: initial !important;
|
|
4487
|
-
}
|
|
4488
|
-
.wds-chevron-container {
|
|
4489
|
-
width: 32px;
|
|
4490
|
-
width: var(--size-32);
|
|
4491
|
-
overflow: hidden;
|
|
4492
|
-
color: var(--color-interactive-primary);
|
|
4493
|
-
margin-left: 8px;
|
|
4494
|
-
margin-left: var(--size-8);
|
|
4495
|
-
transition: width 0.3s ease;
|
|
4496
|
-
}
|
|
4497
|
-
.wds-chevron-hidden {
|
|
4498
|
-
width: 0;
|
|
4499
|
-
}
|
|
4500
|
-
.wds-expressive-money-input-currency-selector {
|
|
4501
|
-
flex-shrink: 0;
|
|
4502
|
-
margin-right: 24px;
|
|
4503
|
-
margin-right: var(--size-24);
|
|
4504
|
-
}
|
|
4505
|
-
.wds-expressive-money-input-chevron {
|
|
4506
|
-
transform: translateY(-5%);
|
|
4507
|
-
}
|
|
4508
4458
|
.np-navigation-option {
|
|
4509
4459
|
-webkit-text-decoration: none;
|
|
4510
4460
|
text-decoration: none;
|
package/src/main.less
CHANGED
|
@@ -51,7 +51,6 @@
|
|
|
51
51
|
@import "./logo/Logo.less";
|
|
52
52
|
@import "./modal/Modal.less";
|
|
53
53
|
@import "./moneyInput/MoneyInput.less";
|
|
54
|
-
@import "./expressiveMoneyInput/ExpressiveMoneyInput.less";
|
|
55
54
|
@import "./navigationOption/NavigationOption.less";
|
|
56
55
|
@import "./navigationOptionsList/NavigationOptionsList.less";
|
|
57
56
|
@import "./nudge/Nudge.less";
|
|
@@ -38,6 +38,14 @@
|
|
|
38
38
|
flex-shrink: 0;
|
|
39
39
|
width: auto;
|
|
40
40
|
}
|
|
41
|
+
.tw-money-input .input-group-addon:not(.amount-currency-select-btn):not(.tw-money-input__fixed-currency):not(:has(~ .tw-money-input__fixed-currency)) {
|
|
42
|
+
padding-right: 0 !important;
|
|
43
|
+
}
|
|
44
|
+
[dir="rtl"] .tw-money-input .input-group-addon:not(.amount-currency-select-btn):not(.tw-money-input__fixed-currency):not(:has(~ .tw-money-input__fixed-currency)) {
|
|
45
|
+
padding-left: 0 !important;
|
|
46
|
+
padding-right: 0 !important;
|
|
47
|
+
padding-right: initial !important;
|
|
48
|
+
}
|
|
41
49
|
.tw-money-input .amount-currency-select-btn {
|
|
42
50
|
flex-shrink: 0;
|
|
43
51
|
width: auto;
|
|
@@ -32,11 +32,16 @@
|
|
|
32
32
|
|
|
33
33
|
.input-group-addon {
|
|
34
34
|
flex-shrink: 0;
|
|
35
|
+
|
|
35
36
|
&:not(.amount-currency-select-btn) {
|
|
36
37
|
display: flex;
|
|
37
38
|
align-items: center;
|
|
38
39
|
flex-shrink: 0;
|
|
39
40
|
width: auto;
|
|
41
|
+
|
|
42
|
+
&:not(.tw-money-input__fixed-currency):not(:has(~ .tw-money-input__fixed-currency)) {
|
|
43
|
+
.padding(right, 0) !important;
|
|
44
|
+
}
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
|
|
@@ -91,26 +91,26 @@
|
|
|
91
91
|
background-color: var(--color-sentiment-positive-secondary-active);
|
|
92
92
|
}
|
|
93
93
|
.wds-inline-prompt--proposition {
|
|
94
|
-
background-color:
|
|
95
|
-
color: var(--color-
|
|
94
|
+
background-color: var(--color-sentiment-positive-secondary);
|
|
95
|
+
color: var(--color-sentiment-positive-primary);
|
|
96
96
|
}
|
|
97
97
|
.wds-inline-prompt--proposition a,
|
|
98
98
|
.wds-inline-prompt--proposition button {
|
|
99
|
-
color: var(--color-
|
|
99
|
+
color: var(--color-sentiment-positive-primary);
|
|
100
100
|
}
|
|
101
101
|
.wds-inline-prompt--proposition a:hover,
|
|
102
102
|
.wds-inline-prompt--proposition button:hover {
|
|
103
|
-
color: var(--color-
|
|
103
|
+
color: var(--color-sentiment-positive-primary-hover);
|
|
104
104
|
}
|
|
105
105
|
.wds-inline-prompt--proposition a:active,
|
|
106
106
|
.wds-inline-prompt--proposition button:active {
|
|
107
|
-
color: var(--color-
|
|
107
|
+
color: var(--color-sentiment-positive-primary-active);
|
|
108
108
|
}
|
|
109
109
|
.wds-inline-prompt.wds-inline-prompt--proposition:has(a, button):hover {
|
|
110
|
-
background-color:
|
|
110
|
+
background-color: var(--color-sentiment-positive-secondary-hover);
|
|
111
111
|
}
|
|
112
112
|
.wds-inline-prompt.wds-inline-prompt--proposition:has(a, button):active {
|
|
113
|
-
background-color:
|
|
113
|
+
background-color: var(--color-sentiment-positive-secondary-active);
|
|
114
114
|
}
|
|
115
115
|
.wds-inline-prompt--neutral {
|
|
116
116
|
background-color: rgba(134,167,189,0.10196);
|
|
@@ -94,26 +94,26 @@
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
&--proposition {
|
|
97
|
-
background-color:
|
|
97
|
+
background-color: var(--color-sentiment-positive-secondary);
|
|
98
98
|
|
|
99
|
-
color: var(--color-
|
|
99
|
+
color: var(--color-sentiment-positive-primary);
|
|
100
100
|
|
|
101
101
|
a, button {
|
|
102
|
-
color: var(--color-
|
|
102
|
+
color: var(--color-sentiment-positive-primary);
|
|
103
103
|
&:hover {
|
|
104
|
-
color: var(--color-
|
|
104
|
+
color: var(--color-sentiment-positive-primary-hover);
|
|
105
105
|
}
|
|
106
106
|
&:active {
|
|
107
|
-
color: var(--color-
|
|
107
|
+
color: var(--color-sentiment-positive-primary-active);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
.wds-inline-prompt&:has(a, button) {
|
|
112
112
|
&:hover {
|
|
113
|
-
background-color:
|
|
113
|
+
background-color: var(--color-sentiment-positive-secondary-hover);
|
|
114
114
|
}
|
|
115
115
|
&:active {
|
|
116
|
-
background-color:
|
|
116
|
+
background-color: var(--color-sentiment-positive-secondary-active);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
}
|
|
@@ -15,12 +15,6 @@ describe('InlinePrompt', () => {
|
|
|
15
15
|
expect(screen.getByText('Hello world')).toBeInTheDocument();
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
it('renders with GiftBox icon as default for `proposition` sentiment', () => {
|
|
19
|
-
render(<InlinePrompt {...defaultProps} sentiment="proposition" />);
|
|
20
|
-
expect(screen.getByText('Prompt message')).toBeInTheDocument();
|
|
21
|
-
expect(screen.getByTestId('gift-box-icon')).toBeInTheDocument();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
18
|
describe('renders with each sentiment', () => {
|
|
25
19
|
it.each([Sentiment.POSITIVE, Sentiment.NEUTRAL, Sentiment.NEGATIVE, Sentiment.WARNING])(
|
|
26
20
|
'renders with sentiment %s',
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Sentiment } from '../../common';
|
|
2
|
-
import { BackslashCircle
|
|
2
|
+
import { BackslashCircle } from '@transferwise/icons';
|
|
3
3
|
import ProcessIndicator from '../../processIndicator';
|
|
4
4
|
import StatusIcon from '../../statusIcon';
|
|
5
5
|
import { clsx } from 'clsx';
|
|
6
6
|
import Body from '../../body';
|
|
7
7
|
|
|
8
8
|
export type InlinePromptProps = {
|
|
9
|
-
sentiment?:
|
|
10
|
-
| `${Sentiment.POSITIVE | Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.WARNING}`
|
|
11
|
-
| 'proposition';
|
|
9
|
+
sentiment?: `${Sentiment.POSITIVE | Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.WARNING}`;
|
|
12
10
|
loading?: boolean;
|
|
13
11
|
/**
|
|
14
12
|
* Use for short-lived inline prompts to avoid swap of the icon (which is bad UX for short-lived prompts, e.g. when submit form)
|
|
@@ -18,7 +16,6 @@ export type InlinePromptProps = {
|
|
|
18
16
|
className?: string;
|
|
19
17
|
'data-testid'?: string;
|
|
20
18
|
children: React.ReactNode;
|
|
21
|
-
media?: React.ReactNode;
|
|
22
19
|
};
|
|
23
20
|
|
|
24
21
|
export const InlinePrompt = ({
|
|
@@ -27,16 +24,9 @@ export const InlinePrompt = ({
|
|
|
27
24
|
loading = false,
|
|
28
25
|
className,
|
|
29
26
|
children,
|
|
30
|
-
media = null,
|
|
31
27
|
...rest
|
|
32
28
|
}: InlinePromptProps) => {
|
|
33
29
|
const renderMedia = () => {
|
|
34
|
-
if (media && ['proposition', 'positive'].includes(sentiment)) {
|
|
35
|
-
return media;
|
|
36
|
-
}
|
|
37
|
-
if (sentiment === 'proposition') {
|
|
38
|
-
return <GiftBox />;
|
|
39
|
-
}
|
|
40
30
|
if (muted) {
|
|
41
31
|
return <BackslashCircle size={16} data-testid="InlinePrompt_Muted" />;
|
|
42
32
|
}
|
package/src/ssr.spec.tsx
CHANGED
|
@@ -92,7 +92,6 @@ 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: [] },
|
|
96
95
|
steps: [],
|
|
97
96
|
stepper: {
|
|
98
97
|
steps: [],
|
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var formatting = require('@transferwise/formatting');
|
|
4
|
-
var clsx = require('clsx');
|
|
5
|
-
var framerMotion = require('framer-motion');
|
|
6
|
-
var React = require('react');
|
|
7
|
-
var reactIntl = require('react-intl');
|
|
8
|
-
var AnimatedNumber = require('./AnimatedNumber.js');
|
|
9
|
-
var useFocus = require('./useFocus.js');
|
|
10
|
-
var useInputStyle = require('./useInputStyle.js');
|
|
11
|
-
var utils = require('./utils.js');
|
|
12
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
13
|
-
|
|
14
|
-
const AmountInput = ({
|
|
15
|
-
id,
|
|
16
|
-
describedById,
|
|
17
|
-
amount,
|
|
18
|
-
currency,
|
|
19
|
-
autoFocus,
|
|
20
|
-
onChange,
|
|
21
|
-
onFocusChange,
|
|
22
|
-
loading
|
|
23
|
-
}) => {
|
|
24
|
-
const intl = reactIntl.useIntl();
|
|
25
|
-
const {
|
|
26
|
-
focus,
|
|
27
|
-
setFocus,
|
|
28
|
-
visualFocus,
|
|
29
|
-
setVisualFocus
|
|
30
|
-
} = useFocus.useFocus();
|
|
31
|
-
const [value, setValue] = React.useState(amount ? utils.getFormattedString({
|
|
32
|
-
value: amount,
|
|
33
|
-
currency,
|
|
34
|
-
locale: intl.locale
|
|
35
|
-
}) : '');
|
|
36
|
-
const numericValue = React.useMemo(() => {
|
|
37
|
-
return utils.getUnformattedNumber({
|
|
38
|
-
value,
|
|
39
|
-
currency,
|
|
40
|
-
locale: intl.locale
|
|
41
|
-
});
|
|
42
|
-
}, [value, currency, intl.locale]);
|
|
43
|
-
const valueWithFullDecimals = React.useMemo(() => {
|
|
44
|
-
return utils.getFormattedString({
|
|
45
|
-
value: numericValue ?? 0,
|
|
46
|
-
currency,
|
|
47
|
-
locale: intl.locale,
|
|
48
|
-
alwaysShowDecimals: true
|
|
49
|
-
});
|
|
50
|
-
}, [numericValue, currency, intl.locale]);
|
|
51
|
-
const ref = React.useRef(null);
|
|
52
|
-
React.useEffect(() => {
|
|
53
|
-
if (autoFocus) {
|
|
54
|
-
ref.current?.focus();
|
|
55
|
-
}
|
|
56
|
-
}, []);
|
|
57
|
-
const placeholder = getPlaceholder(currency, intl.locale);
|
|
58
|
-
const groupSeparator = utils.getGroupSeparator(currency, intl.locale);
|
|
59
|
-
const decimalSeparator = utils.getDecimalSeparator(currency, intl.locale);
|
|
60
|
-
const maxDecimalCount = utils.getDecimalCount(currency, intl.locale);
|
|
61
|
-
const decimalPart = getDecimalPart(value, decimalSeparator);
|
|
62
|
-
const decimalMode = decimalSeparator && value.includes(decimalSeparator);
|
|
63
|
-
React.useEffect(() => {
|
|
64
|
-
if (!focus) {
|
|
65
|
-
setValue(amount ? utils.getFormattedString({
|
|
66
|
-
value: amount,
|
|
67
|
-
currency,
|
|
68
|
-
locale: intl.locale
|
|
69
|
-
}) : '');
|
|
70
|
-
}
|
|
71
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
72
|
-
}, [amount]);
|
|
73
|
-
React.useEffect(() => {
|
|
74
|
-
onFocusChange?.(visualFocus);
|
|
75
|
-
}, [visualFocus]);
|
|
76
|
-
const shouldReformatAfterUserInput = newValue => {
|
|
77
|
-
// don't reformat if formatting would wipe out user's input
|
|
78
|
-
if (reformatValue(newValue) === '') {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);
|
|
82
|
-
const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);
|
|
83
|
-
// if the user has entered a seperator to the end, formatting would delete it
|
|
84
|
-
if (endsWithDecimalSeparator || endsWithGroupSeparator) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);
|
|
88
|
-
if (containsDecimalSeparator) {
|
|
89
|
-
const enteredDecimalsCount = utils.getEnteredDecimalsCount(newValue, decimalSeparator);
|
|
90
|
-
// don't reformat until user has entered all the allowed decimals
|
|
91
|
-
// for example, we don't want 1.1 to be reformatted to 1.10 immediately
|
|
92
|
-
if (enteredDecimalsCount < maxDecimalCount) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return true;
|
|
97
|
-
};
|
|
98
|
-
const reformatValue = newValue => {
|
|
99
|
-
const unformattedValue = utils.getUnformattedNumber({
|
|
100
|
-
value: newValue,
|
|
101
|
-
currency,
|
|
102
|
-
locale: intl.locale
|
|
103
|
-
});
|
|
104
|
-
const formattedValue = unformattedValue ? utils.getFormattedString({
|
|
105
|
-
value: unformattedValue,
|
|
106
|
-
currency,
|
|
107
|
-
locale: intl.locale
|
|
108
|
-
}) : '';
|
|
109
|
-
return formattedValue;
|
|
110
|
-
};
|
|
111
|
-
const handleChange = newValue => {
|
|
112
|
-
const oldCursorPosition = ref.current?.selectionStart ?? 0;
|
|
113
|
-
const newFormattedString = shouldReformatAfterUserInput(newValue) ? reformatValue(newValue) : newValue;
|
|
114
|
-
setValue(newFormattedString);
|
|
115
|
-
const newNumber = utils.getUnformattedNumber({
|
|
116
|
-
value: newFormattedString,
|
|
117
|
-
currency,
|
|
118
|
-
locale: intl.locale
|
|
119
|
-
});
|
|
120
|
-
if (newNumber !== numericValue) {
|
|
121
|
-
if (numericValue || newNumber) {
|
|
122
|
-
onChange(newNumber);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);
|
|
126
|
-
requestAnimationFrame(() => {
|
|
127
|
-
ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
const handlePaste = e => {
|
|
131
|
-
e.preventDefault();
|
|
132
|
-
const clipboardData = e.clipboardData?.getData('text/plain');
|
|
133
|
-
if (!clipboardData) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
// need to sanitise the pasted value otherwise other validation logic will ignore the input entirely
|
|
137
|
-
const sanitisedValue = reformatValue(clipboardData);
|
|
138
|
-
handleChange(sanitisedValue);
|
|
139
|
-
};
|
|
140
|
-
const handleBlur = () => {
|
|
141
|
-
setFocus(false);
|
|
142
|
-
setValue(reformatValue(value));
|
|
143
|
-
};
|
|
144
|
-
const handleBackspace = e => {
|
|
145
|
-
const input = e.target;
|
|
146
|
-
// using the updated selection range after the backspace key has been processed, instead of the current selection range in state
|
|
147
|
-
const {
|
|
148
|
-
value: currentValue,
|
|
149
|
-
selectionStart,
|
|
150
|
-
selectionEnd
|
|
151
|
-
} = input;
|
|
152
|
-
if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {
|
|
153
|
-
const charBeforeCursor = currentValue[selectionStart - 1];
|
|
154
|
-
// if the user deletes a thousands separator, remove the digit before it as well
|
|
155
|
-
if (charBeforeCursor === groupSeparator) {
|
|
156
|
-
e.preventDefault();
|
|
157
|
-
const beforeCursor = currentValue.slice(0, selectionStart - 2);
|
|
158
|
-
const afterCursor = currentValue.slice(selectionStart);
|
|
159
|
-
const newValue = `${beforeCursor}${afterCursor}`;
|
|
160
|
-
input.setSelectionRange(beforeCursor.length, beforeCursor.length);
|
|
161
|
-
handleChange(newValue);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
const handleKeyDown = e => {
|
|
166
|
-
setFocus(true);
|
|
167
|
-
if (!utils.isAllowedInputKey(e)) {
|
|
168
|
-
e.preventDefault();
|
|
169
|
-
}
|
|
170
|
-
if (e.key === 'Backspace') {
|
|
171
|
-
handleBackspace(e);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
const isAllowedInput = e => {
|
|
175
|
-
const hasMultipleDecimalSeparators = decimalSeparator && e.target.value.split(decimalSeparator).length > 2;
|
|
176
|
-
if (hasMultipleDecimalSeparators) {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
const newNumericValue = utils.getUnformattedNumber({
|
|
180
|
-
value: e.target.value,
|
|
181
|
-
currency,
|
|
182
|
-
locale: intl.locale
|
|
183
|
-
});
|
|
184
|
-
const maxLength = Number.MAX_SAFE_INTEGER.toString().length;
|
|
185
|
-
if (String(newNumericValue).length > maxLength) {
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
return true;
|
|
189
|
-
};
|
|
190
|
-
const addonContent = React.useMemo(() => {
|
|
191
|
-
// because we're using a separate "addon" element for the placeholder decimals, there is a possibility that the input itself will become scrollable
|
|
192
|
-
// and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room
|
|
193
|
-
if (utils.isInputPossiblyOverflowing({
|
|
194
|
-
ref,
|
|
195
|
-
value
|
|
196
|
-
})) {
|
|
197
|
-
return null;
|
|
198
|
-
}
|
|
199
|
-
if (!decimalSeparator || !value) {
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
// if the user has typed a decimal separator, show the full decimal part as a placeholder
|
|
203
|
-
// this returns a string even if there is no content, typing should replace the placeholder immediately without animation
|
|
204
|
-
// otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence
|
|
205
|
-
if (focus && decimalMode) {
|
|
206
|
-
// reuse getDecimalPart
|
|
207
|
-
const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);
|
|
208
|
-
// show only the characters that are not already displayed by the input
|
|
209
|
-
return fullDecimalPart?.slice(decimalPart?.length);
|
|
210
|
-
}
|
|
211
|
-
// in unfocused state, always show the full decimal part unless the user has already entered decimals
|
|
212
|
-
if (!focus && !decimalMode) {
|
|
213
|
-
const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);
|
|
214
|
-
return decimalSeparator + decimalPlaceholder;
|
|
215
|
-
}
|
|
216
|
-
return null;
|
|
217
|
-
}, [decimalMode, decimalPart?.length, decimalSeparator, focus, placeholder, value, valueWithFullDecimals]);
|
|
218
|
-
const style = useInputStyle.useInputStyle({
|
|
219
|
-
// whenever decimals are shown, we need to account for the full decimal part for the font size calculation
|
|
220
|
-
value: addonContent ? valueWithFullDecimals : value,
|
|
221
|
-
focus: visualFocus,
|
|
222
|
-
inputElement: ref.current,
|
|
223
|
-
loading
|
|
224
|
-
});
|
|
225
|
-
return /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
226
|
-
className: "wds-amount-input-container",
|
|
227
|
-
children: /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
228
|
-
className: clsx.clsx('wds-amount-input-input-container', 'np-text-display-large'),
|
|
229
|
-
style: style,
|
|
230
|
-
children: [/*#__PURE__*/jsxRuntime.jsx("input", {
|
|
231
|
-
ref: ref,
|
|
232
|
-
className: "wds-amount-input-input",
|
|
233
|
-
id: id,
|
|
234
|
-
autoComplete: "off",
|
|
235
|
-
inputMode: "decimal",
|
|
236
|
-
value: value,
|
|
237
|
-
type: "text",
|
|
238
|
-
placeholder: placeholder,
|
|
239
|
-
"aria-describedby": describedById
|
|
240
|
-
/* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */,
|
|
241
|
-
size: 1,
|
|
242
|
-
onChange: e => {
|
|
243
|
-
if (isAllowedInput(e)) {
|
|
244
|
-
handleChange(e.target.value);
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
onBlurCapture: () => handleBlur(),
|
|
248
|
-
onPaste: e => handlePaste(e),
|
|
249
|
-
onFocus: () => {
|
|
250
|
-
setFocus(true);
|
|
251
|
-
},
|
|
252
|
-
onBlur: () => {
|
|
253
|
-
setTimeout(() => setVisualFocus(false), 30);
|
|
254
|
-
},
|
|
255
|
-
onKeyDown: e => handleKeyDown(e)
|
|
256
|
-
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.AnimatePresence, {
|
|
257
|
-
initial: false,
|
|
258
|
-
children: addonContent !== null && /*#__PURE__*/jsxRuntime.jsx(AnimatedNumber.AnimatedNumber, {
|
|
259
|
-
className: clsx.clsx('wds-amount-input-placeholder', visualFocus && 'wds-amount-input-placeholder-focus'),
|
|
260
|
-
onClick: () => ref.current?.focus(),
|
|
261
|
-
children: addonContent
|
|
262
|
-
})
|
|
263
|
-
})]
|
|
264
|
-
})
|
|
265
|
-
});
|
|
266
|
-
};
|
|
267
|
-
const getPlaceholder = (currency, locale) => {
|
|
268
|
-
return formatting.formatAmount(0, currency, locale, {
|
|
269
|
-
alwaysShowDecimals: true
|
|
270
|
-
});
|
|
271
|
-
};
|
|
272
|
-
const getDecimalPart = (value, decimalSeparator) => {
|
|
273
|
-
if (!value || !decimalSeparator) {
|
|
274
|
-
return undefined;
|
|
275
|
-
}
|
|
276
|
-
const [_, decimalPart] = value.split(decimalSeparator);
|
|
277
|
-
return decimalPart ?? undefined;
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
exports.AmountInput = AmountInput;
|
|
281
|
-
//# sourceMappingURL=AmountInput.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInput.js","sources":["../../src/expressiveMoneyInput/AmountInput.tsx"],"sourcesContent":["import { formatAmount } from '@transferwise/formatting';\nimport { clsx } from 'clsx';\nimport { AnimatePresence } from 'framer-motion';\nimport { type ChangeEvent, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { Props as ExpressiveMoneyInputProps } from './ExpressiveMoneyInput';\nimport { AnimatedNumber } from './AnimatedNumber';\nimport { useFocus } from './useFocus';\nimport { useInputStyle } from './useInputStyle';\nimport {\n getDecimalCount,\n getDecimalSeparator,\n getEnteredDecimalsCount,\n getFormattedString,\n getGroupSeparator,\n getUnformattedNumber,\n isAllowedInputKey,\n isInputPossiblyOverflowing,\n} from './utils';\n\ntype Props = {\n id: string;\n describedById?: string;\n amount?: number | null;\n currency: string;\n autoFocus?: boolean;\n onChange: (amount: number | null) => void;\n onFocusChange?: (focused: boolean) => void;\n} & Pick<ExpressiveMoneyInputProps, 'loading'>;\n\nexport const AmountInput = ({\n id,\n describedById,\n amount,\n currency,\n autoFocus,\n onChange,\n onFocusChange,\n loading,\n}: Props) => {\n const intl = useIntl();\n const { focus, setFocus, visualFocus, setVisualFocus } = useFocus();\n\n const [value, setValue] = useState<string>(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n const numericValue = useMemo(() => {\n return getUnformattedNumber({\n value,\n currency,\n locale: intl.locale,\n });\n }, [value, currency, intl.locale]);\n\n const valueWithFullDecimals = useMemo(() => {\n return getFormattedString({\n value: numericValue ?? 0,\n currency,\n locale: intl.locale,\n alwaysShowDecimals: true,\n });\n }, [numericValue, currency, intl.locale]);\n\n const ref = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (autoFocus) {\n ref.current?.focus();\n }\n }, []);\n\n const placeholder = getPlaceholder(currency, intl.locale);\n const groupSeparator = getGroupSeparator(currency, intl.locale);\n const decimalSeparator = getDecimalSeparator(currency, intl.locale);\n const maxDecimalCount = getDecimalCount(currency, intl.locale);\n\n const decimalPart = getDecimalPart(value, decimalSeparator);\n const decimalMode = decimalSeparator && value.includes(decimalSeparator);\n\n useEffect(() => {\n if (!focus) {\n setValue(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [amount]);\n\n useEffect(() => {\n onFocusChange?.(visualFocus);\n }, [visualFocus]);\n\n const shouldReformatAfterUserInput = (newValue: string) => {\n // don't reformat if formatting would wipe out user's input\n if (reformatValue(newValue) === '') {\n return false;\n }\n\n const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);\n const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);\n\n // if the user has entered a seperator to the end, formatting would delete it\n if (endsWithDecimalSeparator || endsWithGroupSeparator) {\n return false;\n }\n\n const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);\n\n if (containsDecimalSeparator) {\n const enteredDecimalsCount = getEnteredDecimalsCount(newValue, decimalSeparator);\n // don't reformat until user has entered all the allowed decimals\n // for example, we don't want 1.1 to be reformatted to 1.10 immediately\n if (enteredDecimalsCount < maxDecimalCount) {\n return false;\n }\n }\n\n return true;\n };\n\n const reformatValue = (newValue: string) => {\n const unformattedValue = getUnformattedNumber({\n value: newValue,\n currency,\n locale: intl.locale,\n });\n const formattedValue = unformattedValue\n ? getFormattedString({\n value: unformattedValue,\n currency,\n locale: intl.locale,\n })\n : '';\n return formattedValue;\n };\n\n const handleChange = (newValue: string) => {\n const oldCursorPosition = ref.current?.selectionStart ?? 0;\n\n const newFormattedString = shouldReformatAfterUserInput(newValue)\n ? reformatValue(newValue)\n : newValue;\n setValue(newFormattedString);\n\n const newNumber = getUnformattedNumber({\n value: newFormattedString,\n currency,\n locale: intl.locale,\n });\n\n if (newNumber !== numericValue) {\n if (numericValue || newNumber) {\n onChange(newNumber);\n }\n }\n\n const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);\n requestAnimationFrame(() => {\n ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n\n const clipboardData = e.clipboardData?.getData('text/plain');\n if (!clipboardData) {\n return;\n }\n\n // need to sanitise the pasted value otherwise other validation logic will ignore the input entirely\n const sanitisedValue = reformatValue(clipboardData);\n\n handleChange(sanitisedValue);\n };\n\n const handleBlur = () => {\n setFocus(false);\n setValue(reformatValue(value));\n };\n\n const handleBackspace = (e: KeyboardEvent<HTMLInputElement>) => {\n const input = e.target as HTMLInputElement;\n // using the updated selection range after the backspace key has been processed, instead of the current selection range in state\n const { value: currentValue, selectionStart, selectionEnd } = input;\n\n if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {\n const charBeforeCursor = currentValue[selectionStart - 1];\n\n // if the user deletes a thousands separator, remove the digit before it as well\n if (charBeforeCursor === groupSeparator) {\n e.preventDefault();\n const beforeCursor = currentValue.slice(0, selectionStart - 2);\n const afterCursor = currentValue.slice(selectionStart);\n const newValue = `${beforeCursor}${afterCursor}`;\n input.setSelectionRange(beforeCursor.length, beforeCursor.length);\n handleChange(newValue);\n }\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n setFocus(true);\n if (!isAllowedInputKey(e)) {\n e.preventDefault();\n }\n\n if (e.key === 'Backspace') {\n handleBackspace(e);\n }\n };\n\n const isAllowedInput = (e: ChangeEvent<HTMLInputElement>) => {\n const hasMultipleDecimalSeparators =\n decimalSeparator && e.target.value.split(decimalSeparator).length > 2;\n if (hasMultipleDecimalSeparators) {\n return false;\n }\n\n const newNumericValue = getUnformattedNumber({\n value: e.target.value,\n currency,\n locale: intl.locale,\n });\n const maxLength = Number.MAX_SAFE_INTEGER.toString().length;\n if (String(newNumericValue).length > maxLength) {\n return false;\n }\n\n return true;\n };\n\n const addonContent = useMemo((): string | null | undefined => {\n // because we're using a separate \"addon\" element for the placeholder decimals, there is a possibility that the input itself will become scrollable\n // and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room\n if (isInputPossiblyOverflowing({ ref, value })) {\n return null;\n }\n if (!decimalSeparator || !value) {\n return null;\n }\n\n // if the user has typed a decimal separator, show the full decimal part as a placeholder\n // this returns a string even if there is no content, typing should replace the placeholder immediately without animation\n // otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence\n if (focus && decimalMode) {\n // reuse getDecimalPart\n const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);\n // show only the characters that are not already displayed by the input\n return fullDecimalPart?.slice(decimalPart?.length);\n }\n\n // in unfocused state, always show the full decimal part unless the user has already entered decimals\n if (!focus && !decimalMode) {\n const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);\n return decimalSeparator + decimalPlaceholder;\n }\n\n return null;\n }, [\n decimalMode,\n decimalPart?.length,\n decimalSeparator,\n focus,\n placeholder,\n value,\n valueWithFullDecimals,\n ]);\n\n const style = useInputStyle({\n // whenever decimals are shown, we need to account for the full decimal part for the font size calculation\n value: addonContent ? valueWithFullDecimals : value,\n focus: visualFocus,\n inputElement: ref.current,\n loading,\n });\n\n return (\n <div className=\"wds-amount-input-container\">\n <div\n className={clsx('wds-amount-input-input-container', 'np-text-display-large')}\n style={style}\n >\n <input\n ref={ref}\n className=\"wds-amount-input-input\"\n id={id}\n autoComplete=\"off\"\n inputMode=\"decimal\"\n value={value}\n type=\"text\"\n placeholder={placeholder}\n aria-describedby={describedById}\n /* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */\n size={1}\n onChange={(e) => {\n if (isAllowedInput(e)) {\n handleChange(e.target.value);\n }\n }}\n onBlurCapture={() => handleBlur()}\n onPaste={(e) => handlePaste(e)}\n onFocus={() => {\n setFocus(true);\n }}\n onBlur={() => {\n setTimeout(() => setVisualFocus(false), 30);\n }}\n onKeyDown={(e) => handleKeyDown(e)}\n />\n <AnimatePresence initial={false}>\n {addonContent !== null && (\n <AnimatedNumber\n className={clsx(\n 'wds-amount-input-placeholder',\n visualFocus && 'wds-amount-input-placeholder-focus',\n )}\n onClick={() => ref.current?.focus()}\n >\n {addonContent}\n </AnimatedNumber>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n};\n\nconst getPlaceholder = (currency: string, locale: string) => {\n return formatAmount(0, currency, locale, { alwaysShowDecimals: true });\n};\n\nconst getDecimalPart = (value: string, decimalSeparator: string | null) => {\n if (!value || !decimalSeparator) {\n return undefined;\n }\n\n const [_, decimalPart] = value.split(decimalSeparator);\n return decimalPart ?? undefined;\n};\n"],"names":["AmountInput","id","describedById","amount","currency","autoFocus","onChange","onFocusChange","loading","intl","useIntl","focus","setFocus","visualFocus","setVisualFocus","useFocus","value","setValue","useState","getFormattedString","locale","numericValue","useMemo","getUnformattedNumber","valueWithFullDecimals","alwaysShowDecimals","ref","useRef","useEffect","current","placeholder","getPlaceholder","groupSeparator","getGroupSeparator","decimalSeparator","getDecimalSeparator","maxDecimalCount","getDecimalCount","decimalPart","getDecimalPart","decimalMode","includes","shouldReformatAfterUserInput","newValue","reformatValue","endsWithDecimalSeparator","endsWith","endsWithGroupSeparator","containsDecimalSeparator","enteredDecimalsCount","getEnteredDecimalsCount","unformattedValue","formattedValue","handleChange","oldCursorPosition","selectionStart","newFormattedString","newNumber","newCursorPosition","length","requestAnimationFrame","setSelectionRange","handlePaste","e","preventDefault","clipboardData","getData","sanitisedValue","handleBlur","handleBackspace","input","target","currentValue","selectionEnd","charBeforeCursor","beforeCursor","slice","afterCursor","handleKeyDown","isAllowedInputKey","key","isAllowedInput","hasMultipleDecimalSeparators","split","newNumericValue","maxLength","Number","MAX_SAFE_INTEGER","toString","String","addonContent","isInputPossiblyOverflowing","fullDecimalPart","_","decimalPlaceholder","style","useInputStyle","inputElement","_jsx","className","children","_jsxs","clsx","autoComplete","inputMode","type","size","onBlurCapture","onPaste","onFocus","onBlur","setTimeout","onKeyDown","AnimatePresence","initial","AnimatedNumber","onClick","formatAmount","undefined"],"mappings":"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"}
|