@transferwise/components 0.0.0-experimental-4a6914a → 0.0.0-experimental-23ee071

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/src/main.css CHANGED
@@ -29430,66 +29430,54 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
29430
29430
  margin-top: -2px;
29431
29431
  }
29432
29432
 
29433
- @container (max-width: 240px) {
29433
+ @container (min-width: 309px) {
29434
29434
  .wds-list-item-gridWrapper .wds-list-item-control-wrapper {
29435
- align-content: start;
29435
+ height: var(--wds-list-item-control-wrapper-height);
29436
+ align-content: center;
29437
+ }
29438
+ .wds-list-item-gridWrapper .wds-list-item-media-image {
29439
+ -o-object-position: center;
29440
+ object-position: center;
29436
29441
  }
29437
29442
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-hasPrompt {
29438
- grid-template-columns: 1fr auto;
29443
+ grid-template-columns: auto 1fr auto;
29439
29444
  grid-template-rows: auto auto auto;
29440
- grid-template-areas: "body control" "info control" "prompt prompt";
29441
- }
29442
- .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-hasPrompt:has(.wds-list-item-button-control) {
29443
- grid-template-columns: 1fr;
29444
- grid-template-rows: auto;
29445
- grid-template-areas: "body" "info" "prompt" "control";
29445
+ grid-template-areas: "media body control" ". info ." ". prompt prompt";
29446
29446
  }
29447
29447
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-noPrompt {
29448
- grid-template-columns: 1fr auto;
29448
+ grid-template-columns: auto 1fr auto;
29449
29449
  grid-template-rows: auto auto;
29450
- grid-template-areas: "body control" "info control";
29451
- }
29452
- .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-noPrompt:has(.wds-list-item-button-control) {
29453
- grid-template-columns: 1fr;
29454
- grid-template-areas: "body" "info" "control";
29450
+ grid-template-areas: "media body control" ". info .";
29455
29451
  }
29456
29452
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-hasPrompt {
29457
- grid-template-columns: 1fr auto;
29453
+ grid-template-columns: auto 1fr auto;
29458
29454
  grid-template-rows: auto auto;
29459
- grid-template-areas: "body control" "prompt prompt";
29460
- }
29461
- .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-hasPrompt:has(.wds-list-item-button-control) {
29462
- grid-template-columns: 1fr;
29463
- grid-template-areas: "body" "prompt" "control";
29455
+ grid-template-areas: "media body control" ". prompt prompt";
29464
29456
  }
29465
29457
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-noPrompt {
29466
- grid-template-columns: 1fr auto;
29458
+ grid-template-columns: auto 1fr auto;
29467
29459
  grid-template-rows: auto;
29468
- grid-template-areas: "body control";
29469
- }
29470
- .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-noPrompt:has(.wds-list-item-button-control) {
29471
- grid-template-columns: 1fr;
29472
- grid-template-areas: "body" "control";
29460
+ grid-template-areas: "media body control";
29473
29461
  }
29474
29462
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-hasInfo-hasPrompt {
29475
- grid-template-columns: 1fr;
29476
- grid-template-rows: auto auto auto;
29477
- grid-template-areas: "body" "info" "prompt";
29463
+ grid-template-columns: auto 1fr;
29464
+ grid-template-rows: auto auto;
29465
+ grid-template-areas: "media body" ". info" ". prompt";
29478
29466
  }
29479
29467
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-hasInfo-noPrompt {
29480
- grid-template-columns: 1fr;
29481
- grid-template-rows: auto auto;
29482
- grid-template-areas: "body" "info";
29468
+ grid-template-columns: auto 1fr;
29469
+ grid-template-rows: auto auto auto;
29470
+ grid-template-areas: "media body" ". info";
29483
29471
  }
29484
29472
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-noInfo-hasPrompt {
29485
- grid-template-columns: 1fr;
29473
+ grid-template-columns: auto 1fr;
29486
29474
  grid-template-rows: auto auto;
29487
- grid-template-areas: "body" "prompt";
29475
+ grid-template-areas: "media body" ". prompt";
29488
29476
  }
29489
29477
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-noInfo-noPrompt {
29490
- grid-template-columns: 1fr;
29478
+ grid-template-columns: auto 1fr;
29491
29479
  grid-template-rows: auto;
29492
- grid-template-areas: "body";
29480
+ grid-template-areas: "media body";
29493
29481
  }
29494
29482
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl .wds-list-item-prompt {
29495
29483
  grid-column: 1 / -1;
@@ -29497,43 +29485,23 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
29497
29485
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-hasPrompt {
29498
29486
  grid-template-columns: 1fr auto;
29499
29487
  grid-template-rows: auto auto auto;
29500
- grid-template-areas: "body control" "info control" "prompt prompt";
29501
- }
29502
- .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-hasPrompt:has(.wds-list-item-button-control) {
29503
- grid-template-columns: 1fr;
29504
- grid-template-rows: auto;
29505
- grid-template-areas: "body" "info" "prompt" "control";
29488
+ grid-template-areas: "body control" "info ." "prompt prompt";
29506
29489
  }
29507
29490
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-noPrompt {
29508
29491
  grid-template-columns: 1fr auto;
29509
29492
  grid-template-rows: auto auto;
29510
- grid-template-areas: "body control" "info control";
29511
- }
29512
- .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-noPrompt:has(.wds-list-item-button-control) {
29513
- grid-template-columns: 1fr;
29514
- grid-template-rows: auto;
29515
- grid-template-areas: "body" "info" "control";
29493
+ grid-template-areas: "body control" "info .";
29516
29494
  }
29517
29495
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-hasPrompt {
29518
29496
  grid-template-columns: 1fr auto;
29519
29497
  grid-template-rows: auto auto;
29520
29498
  grid-template-areas: "body control" "prompt prompt";
29521
29499
  }
29522
- .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-hasPrompt:has(.wds-list-item-button-control) {
29523
- grid-template-columns: 1fr;
29524
- grid-template-rows: auto;
29525
- grid-template-areas: "body" "prompt" "control";
29526
- }
29527
29500
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-noPrompt {
29528
29501
  grid-template-columns: 1fr auto;
29529
29502
  grid-template-rows: auto;
29530
29503
  grid-template-areas: "body control";
29531
29504
  }
29532
- .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-noPrompt:has(.wds-list-item-button-control) {
29533
- grid-template-columns: 1fr;
29534
- grid-template-rows: auto;
29535
- grid-template-areas: "body" "control";
29536
- }
29537
29505
  .wds-list-item-gridWrapper.wds-list-item-noMedia-noControl .wds-list-item-prompt {
29538
29506
  grid-column: 1 / -1;
29539
29507
  }
@@ -29557,27 +29525,9 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
29557
29525
  grid-template-rows: auto;
29558
29526
  grid-template-areas: "body";
29559
29527
  }
29560
- .wds-list-item-gridWrapper .wds-list-item-media {
29561
- display: none;
29562
- }
29563
- .wds-list-item-gridWrapper .wds-list-item-body {
29564
- grid-area: body;
29565
- display: grid;
29566
- grid-template-columns: 1fr;
29567
- justify-items: start;
29568
- grid-gap: 0;
29569
- gap: 0;
29570
- }
29571
- .wds-list-item-gridWrapper .wds-list-item-body .wds-list-item-value {
29572
- text-align: left;
29573
- }
29574
- .wds-list-item-gridWrapper .wds-list-item-button-control--hasPrompt {
29575
- margin-top: 4px;
29576
- margin-top: var(--size-4);
29577
- }
29578
29528
  }
29579
29529
 
29580
- @container (min-width: 240.1px) and (max-width: 308px) {
29530
+ @container (min-width: 241px) and (max-width: 308px) {
29581
29531
  .wds-list-item-gridWrapper .wds-list-item-media-image {
29582
29532
  -o-object-position: bottom left;
29583
29533
  object-position: bottom left;
@@ -29709,54 +29659,66 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
29709
29659
  }
29710
29660
  }
29711
29661
 
29712
- @container (min-width: 308.1px) {
29662
+ @container (max-width: 240px) {
29713
29663
  .wds-list-item-gridWrapper .wds-list-item-control-wrapper {
29714
- height: var(--wds-list-item-control-wrapper-height);
29715
- align-content: center;
29716
- }
29717
- .wds-list-item-gridWrapper .wds-list-item-media-image {
29718
- -o-object-position: center;
29719
- object-position: center;
29664
+ align-content: start;
29720
29665
  }
29721
29666
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-hasPrompt {
29722
- grid-template-columns: auto 1fr auto;
29667
+ grid-template-columns: 1fr auto;
29723
29668
  grid-template-rows: auto auto auto;
29724
- grid-template-areas: "media body control" ". info ." ". prompt prompt";
29669
+ grid-template-areas: "body control" "info control" "prompt prompt";
29670
+ }
29671
+ .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-hasPrompt:has(.wds-list-item-button-control) {
29672
+ grid-template-columns: 1fr;
29673
+ grid-template-rows: auto;
29674
+ grid-template-areas: "body" "info" "prompt" "control";
29725
29675
  }
29726
29676
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-noPrompt {
29727
- grid-template-columns: auto 1fr auto;
29677
+ grid-template-columns: 1fr auto;
29728
29678
  grid-template-rows: auto auto;
29729
- grid-template-areas: "media body control" ". info .";
29679
+ grid-template-areas: "body control" "info control";
29680
+ }
29681
+ .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-hasInfo-noPrompt:has(.wds-list-item-button-control) {
29682
+ grid-template-columns: 1fr;
29683
+ grid-template-areas: "body" "info" "control";
29730
29684
  }
29731
29685
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-hasPrompt {
29732
- grid-template-columns: auto 1fr auto;
29686
+ grid-template-columns: 1fr auto;
29733
29687
  grid-template-rows: auto auto;
29734
- grid-template-areas: "media body control" ". prompt prompt";
29688
+ grid-template-areas: "body control" "prompt prompt";
29689
+ }
29690
+ .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-hasPrompt:has(.wds-list-item-button-control) {
29691
+ grid-template-columns: 1fr;
29692
+ grid-template-areas: "body" "prompt" "control";
29735
29693
  }
29736
29694
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-noPrompt {
29737
- grid-template-columns: auto 1fr auto;
29695
+ grid-template-columns: 1fr auto;
29738
29696
  grid-template-rows: auto;
29739
- grid-template-areas: "media body control";
29697
+ grid-template-areas: "body control";
29698
+ }
29699
+ .wds-list-item-gridWrapper.wds-list-item-hasMedia-hasControl.wds-list-item-noInfo-noPrompt:has(.wds-list-item-button-control) {
29700
+ grid-template-columns: 1fr;
29701
+ grid-template-areas: "body" "control";
29740
29702
  }
29741
29703
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-hasInfo-hasPrompt {
29742
- grid-template-columns: auto 1fr;
29743
- grid-template-rows: auto auto;
29744
- grid-template-areas: "media body" ". info" ". prompt";
29704
+ grid-template-columns: 1fr;
29705
+ grid-template-rows: auto auto auto;
29706
+ grid-template-areas: "body" "info" "prompt";
29745
29707
  }
29746
29708
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-hasInfo-noPrompt {
29747
- grid-template-columns: auto 1fr;
29748
- grid-template-rows: auto auto auto;
29749
- grid-template-areas: "media body" ". info";
29709
+ grid-template-columns: 1fr;
29710
+ grid-template-rows: auto auto;
29711
+ grid-template-areas: "body" "info";
29750
29712
  }
29751
29713
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-noInfo-hasPrompt {
29752
- grid-template-columns: auto 1fr;
29714
+ grid-template-columns: 1fr;
29753
29715
  grid-template-rows: auto auto;
29754
- grid-template-areas: "media body" ". prompt";
29716
+ grid-template-areas: "body" "prompt";
29755
29717
  }
29756
29718
  .wds-list-item-gridWrapper.wds-list-item-hasMedia-noControl.wds-list-item-noInfo-noPrompt {
29757
- grid-template-columns: auto 1fr;
29719
+ grid-template-columns: 1fr;
29758
29720
  grid-template-rows: auto;
29759
- grid-template-areas: "media body";
29721
+ grid-template-areas: "body";
29760
29722
  }
29761
29723
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl .wds-list-item-prompt {
29762
29724
  grid-column: 1 / -1;
@@ -29764,23 +29726,43 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
29764
29726
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-hasPrompt {
29765
29727
  grid-template-columns: 1fr auto;
29766
29728
  grid-template-rows: auto auto auto;
29767
- grid-template-areas: "body control" "info ." "prompt prompt";
29729
+ grid-template-areas: "body control" "info control" "prompt prompt";
29730
+ }
29731
+ .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-hasPrompt:has(.wds-list-item-button-control) {
29732
+ grid-template-columns: 1fr;
29733
+ grid-template-rows: auto;
29734
+ grid-template-areas: "body" "info" "prompt" "control";
29768
29735
  }
29769
29736
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-noPrompt {
29770
29737
  grid-template-columns: 1fr auto;
29771
29738
  grid-template-rows: auto auto;
29772
- grid-template-areas: "body control" "info .";
29739
+ grid-template-areas: "body control" "info control";
29740
+ }
29741
+ .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-hasInfo-noPrompt:has(.wds-list-item-button-control) {
29742
+ grid-template-columns: 1fr;
29743
+ grid-template-rows: auto;
29744
+ grid-template-areas: "body" "info" "control";
29773
29745
  }
29774
29746
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-hasPrompt {
29775
29747
  grid-template-columns: 1fr auto;
29776
29748
  grid-template-rows: auto auto;
29777
29749
  grid-template-areas: "body control" "prompt prompt";
29778
29750
  }
29751
+ .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-hasPrompt:has(.wds-list-item-button-control) {
29752
+ grid-template-columns: 1fr;
29753
+ grid-template-rows: auto;
29754
+ grid-template-areas: "body" "prompt" "control";
29755
+ }
29779
29756
  .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-noPrompt {
29780
29757
  grid-template-columns: 1fr auto;
29781
29758
  grid-template-rows: auto;
29782
29759
  grid-template-areas: "body control";
29783
29760
  }
29761
+ .wds-list-item-gridWrapper.wds-list-item-noMedia-hasControl.wds-list-item-noInfo-noPrompt:has(.wds-list-item-button-control) {
29762
+ grid-template-columns: 1fr;
29763
+ grid-template-rows: auto;
29764
+ grid-template-areas: "body" "control";
29765
+ }
29784
29766
  .wds-list-item-gridWrapper.wds-list-item-noMedia-noControl .wds-list-item-prompt {
29785
29767
  grid-column: 1 / -1;
29786
29768
  }
@@ -29804,6 +29786,24 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
29804
29786
  grid-template-rows: auto;
29805
29787
  grid-template-areas: "body";
29806
29788
  }
29789
+ .wds-list-item-gridWrapper .wds-list-item-media {
29790
+ display: none;
29791
+ }
29792
+ .wds-list-item-gridWrapper .wds-list-item-body {
29793
+ grid-area: body;
29794
+ display: grid;
29795
+ grid-template-columns: 1fr;
29796
+ justify-items: start;
29797
+ grid-gap: 0;
29798
+ gap: 0;
29799
+ }
29800
+ .wds-list-item-gridWrapper .wds-list-item-body .wds-list-item-value {
29801
+ text-align: left;
29802
+ }
29803
+ .wds-list-item-gridWrapper .wds-list-item-button-control--hasPrompt {
29804
+ margin-top: 4px;
29805
+ margin-top: var(--size-4);
29806
+ }
29807
29807
  }
29808
29808
 
29809
29809
  .wds-list-item-prompt {
@@ -1,5 +1,5 @@
1
1
  import { Meta, StoryObj } from '@storybook/react-webpack5';
2
- import { within, userEvent } from 'storybook/test';
2
+ import { within, userEvent, expect } from 'storybook/test';
3
3
  import { Lock } from '@transferwise/icons';
4
4
  import { useState } from 'react';
5
5
 
@@ -155,6 +155,23 @@ export const BalanceCurrencies: Story = {
155
155
  },
156
156
  };
157
157
 
158
+ export const WithDecimals: Story = {
159
+ args: {
160
+ currencies: [],
161
+ selectedCurrency: exampleCurrency.eur,
162
+ decimals: 4,
163
+ amount: 1234.5678,
164
+ },
165
+ play: async ({ canvas }) => {
166
+ const input = canvas.getByRole('textbox');
167
+ await expect(input).toHaveValue('1,234.5678');
168
+ await userEvent.clear(input);
169
+ await userEvent.type(input, '99.123456789');
170
+ await userEvent.tab();
171
+ await expect(input).toHaveValue('99.1235');
172
+ },
173
+ };
174
+
158
175
  export const OpenedInput: Story = {
159
176
  ...MultipleCurrencies,
160
177
  play: async ({ canvasElement }) => {
@@ -253,6 +253,24 @@ describe('Money Input', () => {
253
253
  await userEvent.tab();
254
254
  expect(input).toHaveValue('1,234,567.65');
255
255
  });
256
+
257
+ it('uses custom decimals when specified', async () => {
258
+ customRender({ decimals: 4 });
259
+ const input = getInput();
260
+ await userEvent.clear(input);
261
+ await userEvent.type(input, '1234.56789');
262
+ await userEvent.tab();
263
+ expect(input).toHaveValue('1,234.5679');
264
+ });
265
+
266
+ it('uses custom decimals of 0', async () => {
267
+ customRender({ decimals: 0 });
268
+ const input = getInput();
269
+ await userEvent.clear(input);
270
+ await userEvent.type(input, '1234.56');
271
+ await userEvent.tab();
272
+ expect(input).toHaveValue('1,235');
273
+ });
256
274
  });
257
275
 
258
276
  it('calls onAmountChange with parsed and formatted value', async () => {
@@ -263,6 +281,12 @@ describe('Money Input', () => {
263
281
  expect(initialProps.onAmountChange).toHaveBeenCalledWith(1000.65);
264
282
  });
265
283
 
284
+ it('calls onAmountChange with value rounded to custom decimals', async () => {
285
+ customRender({ decimals: 4, amount: null });
286
+ await userEvent.type(getInput(), '12.34567');
287
+ expect(initialProps.onAmountChange).toHaveBeenCalledWith(12.3457);
288
+ });
289
+
266
290
  it('calls onAmountChange when input value is empty', async () => {
267
291
  customRender();
268
292
  await userEvent.clear(getInput());
@@ -24,7 +24,7 @@ import {
24
24
  import Title from '../title';
25
25
 
26
26
  import messages from './MoneyInput.messages';
27
- import { formatAmount, parseAmount } from './currencyFormatting';
27
+ import { formatAmount, formatNumber, parseAmount } from './currencyFormatting';
28
28
  import withId from '../withId';
29
29
 
30
30
  export interface CurrencyOptionItem {
@@ -48,24 +48,34 @@ const formatAmountIfSet = ({
48
48
  amount,
49
49
  currency,
50
50
  locale,
51
+ decimals,
51
52
  }: {
52
53
  amount: number | null | undefined;
53
54
  currency: string;
54
55
  locale: string;
56
+ decimals?: number;
55
57
  }) => {
56
- return typeof amount === 'number' ? formatAmount(amount, currency, locale) : '';
58
+ if (typeof amount !== 'number') {
59
+ return '';
60
+ }
61
+ if (decimals != null) {
62
+ return formatNumber(amount, locale, decimals);
63
+ }
64
+ return formatAmount(amount, currency, locale);
57
65
  };
58
66
 
59
67
  const parseNumber = ({
60
68
  amount,
61
69
  currency,
62
70
  locale,
71
+ decimals,
63
72
  }: {
64
73
  amount: string;
65
74
  currency: string;
66
75
  locale: string;
76
+ decimals?: number;
67
77
  }) => {
68
- return parseAmount(amount, currency, locale);
78
+ return parseAmount(amount, currency, locale, decimals);
69
79
  };
70
80
 
71
81
  const allowedInputKeys = new Set([
@@ -102,6 +112,11 @@ export interface MoneyInputProps extends WrappedComponentProps {
102
112
  onCustomAction?: () => void;
103
113
  classNames?: Record<string, string>;
104
114
  selectProps?: Partial<SelectInputProps<CurrencyOptionItem>>;
115
+ /**
116
+ * Specify the number of decimal places to format the amount. When not specified, the number of
117
+ * decimals is determined by the selected currency (e.g. 2 for EUR, 0 for JPY, 3 for BHD).
118
+ */
119
+ decimals?: number;
105
120
  }
106
121
 
107
122
  export type MoneyInputPropsWithInputAttributes = MoneyInputProps &
@@ -133,6 +148,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
133
148
  amount: props.amount,
134
149
  currency: props.selectedCurrency.currency,
135
150
  locale: props.intl.locale,
151
+ decimals: props.decimals,
136
152
  }),
137
153
  locale: props.intl.locale,
138
154
  };
@@ -147,6 +163,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
147
163
  amount: nextProps.amount,
148
164
  currency: nextProps.selectedCurrency.currency,
149
165
  locale: nextProps.intl.locale,
166
+ decimals: nextProps.decimals,
150
167
  }),
151
168
  });
152
169
  }
@@ -174,6 +191,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
174
191
  amount: paste,
175
192
  currency: this.props.selectedCurrency.currency,
176
193
  locale,
194
+ decimals: this.props.decimals,
177
195
  });
178
196
 
179
197
  if (isNumberOrNull(parsed)) {
@@ -182,6 +200,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
182
200
  amount: parsed,
183
201
  currency: this.props.selectedCurrency.currency,
184
202
  locale,
203
+ decimals: this.props.decimals,
185
204
  }),
186
205
  });
187
206
  this.props.onAmountChange?.(parsed);
@@ -201,6 +220,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
201
220
  amount: value,
202
221
  currency: this.props.selectedCurrency.currency,
203
222
  locale: this.state.locale,
223
+ decimals: this.props.decimals,
204
224
  });
205
225
  if (isNumberOrNull(parsed)) {
206
226
  this.props.onAmountChange?.(parsed);
@@ -248,6 +268,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
248
268
  amount: previousState.formattedAmount,
249
269
  currency: this.props.selectedCurrency.currency,
250
270
  locale: previousState.locale,
271
+ decimals: this.props.decimals,
251
272
  });
252
273
  if (!isNumberOrNull(parsed)) {
253
274
  return {
@@ -259,6 +280,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
259
280
  amount: parsed,
260
281
  currency: this.props.selectedCurrency.currency,
261
282
  locale: previousState.locale,
283
+ decimals: this.props.decimals,
262
284
  }),
263
285
  };
264
286
  });
@@ -340,6 +362,7 @@ class MoneyInput extends Component<MoneyInputPropsWithInputAttributes, MoneyInpu
340
362
  amount: this.props.placeholder,
341
363
  currency: this.props.selectedCurrency.currency,
342
364
  locale: this.state.locale,
365
+ decimals: this.props.decimals,
343
366
  })}
344
367
  autoComplete="off"
345
368
  aria-describedby={selectedCurrencyElementId}
@@ -1,8 +1,8 @@
1
- import { formatAmount } from '@transferwise/formatting';
1
+ import { formatAmount, formatNumber } from '@transferwise/formatting';
2
2
 
3
3
  import { DEFAULT_LOCALE } from '../common/locale';
4
4
 
5
- export { formatAmount };
5
+ export { formatAmount, formatNumber };
6
6
 
7
7
  // TODO: do not duplicate this between formatting and components
8
8
  const currencyDecimals: Record<string, number> = {
@@ -61,10 +61,15 @@ function getDecimalSeparator(locale: string) {
61
61
  return isNumberLocaleSupported() ? (1.1).toLocaleString(locale)[1] : '.';
62
62
  }
63
63
 
64
- export function parseAmount(number: string, currency: string, locale = DEFAULT_LOCALE) {
64
+ export function parseAmount(
65
+ number: string,
66
+ currency: string,
67
+ locale = DEFAULT_LOCALE,
68
+ decimals?: number,
69
+ ) {
65
70
  const validLocale = getValidLocale(locale);
66
71
 
67
- const precision = getCurrencyDecimals(currency);
72
+ const precision = decimals ?? getCurrencyDecimals(currency);
68
73
  const groupSeparator = isNumberLocaleSupported() ? (10000).toLocaleString(validLocale)[2] : ',';
69
74
  const decimalSeparator = getDecimalSeparator(validLocale);
70
75
  const numberWithStandardDecimalSeparator = (number || '')
@@ -1,67 +0,0 @@
1
- import List from '../../list';
2
-
3
- import { ListItem, type ListItemProps } from '../ListItem';
4
- import {
5
- InfoCircle,
6
- Documents,
7
- Warning,
8
- Home,
9
- Globe,
10
- People,
11
- Link as LinkIcon,
12
- } from '@transferwise/icons';
13
-
14
- export default {
15
- title: 'Aidan',
16
- };
17
-
18
- export const Testing = {
19
- render: () => {
20
- return (
21
- <div
22
- style={{
23
- display: 'flex',
24
- gap: 'var(--size-4)',
25
- flexDirection: 'row',
26
- width: '689px',
27
- // border: '1px solid black',
28
- }}
29
- >
30
- <div
31
- style={{
32
- flex: 1,
33
- }}
34
- >
35
- <div
36
- style={{
37
- border: '1px solid var(--color-border-neutral)',
38
- borderRadius: 'var(--radius-medium)',
39
- padding: 'var(--size-16)',
40
- display: 'flex',
41
- justifyContent: 'center',
42
- }}
43
- >
44
- <ListItem
45
- title="System maintenance"
46
- subtitle="Scheduled downtime"
47
- inverted
48
- control={
49
- <ListItem.IconButton partiallyInteractive>
50
- <InfoCircle />
51
- </ListItem.IconButton>
52
- }
53
- />
54
- </div>
55
- </div>
56
-
57
- <div
58
- style={{
59
- flex: 1,
60
- }}
61
- >
62
- <span>a</span>
63
- </div>
64
- </div>
65
- );
66
- },
67
- };