From 0683e6e3d3b829d67cd03d3f69fdae4dbb0e39d0 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 3 May 2023 11:10:06 +0300 Subject: [PATCH 01/52] refactor: init pr From 9bf3f9ec0362fbce9dbc92486e68151340b73148 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 01:05:14 +0300 Subject: [PATCH 02/52] feat: transfer amount input field core logic --- .../components/transfer-amount-input/index.ts | 4 +++ .../transfer-amount-input.scss | 4 +++ .../transfer-amount-input.tsx | 32 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 packages/components/src/components/transfer-amount-input/index.ts create mode 100644 packages/components/src/components/transfer-amount-input/transfer-amount-input.scss create mode 100644 packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx diff --git a/packages/components/src/components/transfer-amount-input/index.ts b/packages/components/src/components/transfer-amount-input/index.ts new file mode 100644 index 000000000000..bc5e11d204c1 --- /dev/null +++ b/packages/components/src/components/transfer-amount-input/index.ts @@ -0,0 +1,4 @@ +import TransferAmountInput from './transfer-amount-input'; +import './transfer-amount-input.scss'; + +export default TransferAmountInput; diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss b/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss new file mode 100644 index 000000000000..d99d2aa16f3d --- /dev/null +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss @@ -0,0 +1,4 @@ +.transfer-amount-input-wrapper { + display: flex; + flex-direction: column; +} diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx new file mode 100644 index 000000000000..8e7fe5526659 --- /dev/null +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import Input from '../input'; + +type TTransferAmountInput = { + className?: string; + currency: string; + disabled?: boolean; + initialValue?: number; + label?: React.ReactNode; +}; + +const TransferAmountInput = ({ className, currency, initialValue, disabled, label }: TTransferAmountInput) => { + return ( +
+ {label} + { + let input_value = e.target.value; + input_value = input_value.replace(/\D/g, ''); + input_value = (Number(input_value) / 100).toLocaleString('en-US', { minimumFractionDigits: 2 }); + e.target.value = input_value; + }} + /> +
+ ); +}; + +Input.displayName = 'TransferAmountInput'; + +export default TransferAmountInput; From 9e1c2ee6862be8e866ccbc863b181d7ccffb69ca Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 02:39:07 +0300 Subject: [PATCH 03/52] refactor: core logic changed a bit --- .../transfer-amount-input/transfer-amount-input.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx index 8e7fe5526659..1503bd70ae41 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import Input from '../input'; type TTransferAmountInput = { @@ -9,19 +9,22 @@ type TTransferAmountInput = { label?: React.ReactNode; }; -const TransferAmountInput = ({ className, currency, initialValue, disabled, label }: TTransferAmountInput) => { +const TransferAmountInput = ({ className, currency, disabled = false, initialValue, label }: TTransferAmountInput) => { + const [value, setValue] = useState(0); + return (
{label} { let input_value = e.target.value; input_value = input_value.replace(/\D/g, ''); - input_value = (Number(input_value) / 100).toLocaleString('en-US', { minimumFractionDigits: 2 }); - e.target.value = input_value; + setValue(Number(input_value) / 100); }} + type={'text'} + placeholder={`${value.toLocaleString('en-US', { minimumFractionDigits: 2 })} USD`} />
); From 28ac0e43da9b972c82d2da000aff6126827d8459 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 07:46:54 +0300 Subject: [PATCH 04/52] refactor: basic styles --- .../__tests__/transfer-amount-input.test.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx diff --git a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx new file mode 100644 index 000000000000..7b26396e6ee3 --- /dev/null +++ b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import TransferAmountInput from '../transfer-amount-input'; + +describe('', () => { + it('should render with the initial value of "0.00"', () => { + render(); + }); + + it('should not change the value on non-numeric and non-"." inputs', () => { + render(); + }); + + it('should change the value like an ATM, i.e. from right to left, when entering digits', () => { + render(); + }); + + it('should add commas for big values', () => { + render(); + }); + + it('should not remove "0.00" when backspacing', () => { + render(); + }); +}); From d4f32e8afb8359041dad4bdc4e86872493e16d65 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 07:50:45 +0300 Subject: [PATCH 05/52] refactor: basic styles (the right one) --- .../transfer-amount-input.scss | 16 ++++++++++++++++ .../transfer-amount-input.tsx | 5 +++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss b/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss index d99d2aa16f3d..02a9a8d6bce8 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss @@ -1,4 +1,20 @@ .transfer-amount-input-wrapper { display: flex; flex-direction: column; + + span { + font-size: 14px; + line-height: 20px; + } +} + +.transfer-amount-input { + border: none; + line-height: 30px; + + input { + font-size: 20px; + font-weight: 700; + padding: 0; + } } diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx index 1503bd70ae41..2be44fa9bce7 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx @@ -13,10 +13,10 @@ const TransferAmountInput = ({ className, currency, disabled = false, initialVal const [value, setValue] = useState(0); return ( -
+
{label} { let input_value = e.target.value; @@ -25,6 +25,7 @@ const TransferAmountInput = ({ className, currency, disabled = false, initialVal }} type={'text'} placeholder={`${value.toLocaleString('en-US', { minimumFractionDigits: 2 })} USD`} + value={value.toLocaleString('en-US', { minimumFractionDigits: 2 })} />
); From 951a19b14366e7044b3be597f9c07109fd963b69 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 08:26:53 +0300 Subject: [PATCH 06/52] refactor: tests --- .../__tests__/transfer-amount-input.test.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx index 7b26396e6ee3..3b732dd3be85 100644 --- a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx +++ b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx @@ -1,25 +1,41 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import TransferAmountInput from '../transfer-amount-input'; describe('', () => { it('should render with the initial value of "0.00"', () => { render(); + const input = screen.getByRole('textbox'); + expect(input).toHaveDisplayValue('0.00'); }); it('should not change the value on non-numeric and non-"." inputs', () => { render(); + const input = screen.getByRole('textbox'); + fireEvent.change(input, { target: { value: 'abcdef!@#$%^&*()_+-={}[];\'"|\\/,.<>' } }); + expect(input).toHaveDisplayValue('0.00'); }); it('should change the value like an ATM, i.e. from right to left, when entering digits', () => { render(); + const input = screen.getByRole('textbox'); + fireEvent.change(input, { target: { value: '1' } }); + expect(input).toHaveDisplayValue('0.01'); + fireEvent.change(input, { target: { value: '12' } }); + expect(input).toHaveDisplayValue('0.12'); + fireEvent.change(input, { target: { value: '123' } }); + expect(input).toHaveDisplayValue('1.23'); }); it('should add commas for big values', () => { render(); + const input = screen.getByRole('textbox'); + fireEvent.change(input, { target: { value: '1234567890' } }); + expect(input).toHaveDisplayValue('12,345,678.90'); }); it('should not remove "0.00" when backspacing', () => { render(); + const input = screen.getByRole('textbox'); }); }); From f760c636d9cd64b5894562ecb13c532098fb119c Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 08:38:11 +0300 Subject: [PATCH 07/52] refactor: backspacing test --- .../__tests__/transfer-amount-input.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx index 3b732dd3be85..054949c02f2e 100644 --- a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx +++ b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx @@ -37,5 +37,7 @@ describe('', () => { it('should not remove "0.00" when backspacing', () => { render(); const input = screen.getByRole('textbox'); + fireEvent.change(input, { target: { value: '0' } }); + expect(input).toHaveDisplayValue('0.00'); }); }); From 166c3896311beaf91be2abf12e4c24410978c7d0 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 08:58:20 +0300 Subject: [PATCH 08/52] refactor: fireEvent -> userEvent --- .../__tests__/transfer-amount-input.test.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx index 054949c02f2e..06f05dc08e9b 100644 --- a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx +++ b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import TransferAmountInput from '../transfer-amount-input'; describe('', () => { @@ -12,32 +13,34 @@ describe('', () => { it('should not change the value on non-numeric and non-"." inputs', () => { render(); const input = screen.getByRole('textbox'); - fireEvent.change(input, { target: { value: 'abcdef!@#$%^&*()_+-={}[];\'"|\\/,.<>' } }); + userEvent.type(input, 'abcdef!@#$%^&*()_+-={}[];\'"|\\/,.<>'); expect(input).toHaveDisplayValue('0.00'); }); it('should change the value like an ATM, i.e. from right to left, when entering digits', () => { render(); const input = screen.getByRole('textbox'); - fireEvent.change(input, { target: { value: '1' } }); + userEvent.type(input, '1'); expect(input).toHaveDisplayValue('0.01'); - fireEvent.change(input, { target: { value: '12' } }); + userEvent.type(input, '2'); expect(input).toHaveDisplayValue('0.12'); - fireEvent.change(input, { target: { value: '123' } }); + userEvent.type(input, '3'); expect(input).toHaveDisplayValue('1.23'); }); it('should add commas for big values', () => { render(); const input = screen.getByRole('textbox'); - fireEvent.change(input, { target: { value: '1234567890' } }); + userEvent.type(input, '1234567890'); expect(input).toHaveDisplayValue('12,345,678.90'); }); it('should not remove "0.00" when backspacing', () => { render(); const input = screen.getByRole('textbox'); - fireEvent.change(input, { target: { value: '0' } }); + userEvent.type(input, '100'); + expect(input).toHaveDisplayValue('1.00'); + userEvent.clear(input); expect(input).toHaveDisplayValue('0.00'); }); }); From c5ee462047622104e201b8b5f35344dc2634915b Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 10:19:18 +0300 Subject: [PATCH 09/52] refactor: add the export in index.js --- packages/components/src/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/index.js b/packages/components/src/index.js index b630871908a2..0dd628370bdb 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -105,6 +105,7 @@ export { default as TickPicker } from './components/tick-picker'; export { default as TickProgress } from './components/tick-progress'; export { default as Timeline } from './components/timeline'; export { default as Tooltip } from './components/tooltip'; +export { default as TransferAmountInput } from './components/transfer-amount-input'; export { default as UILoader } from './components/u-i-loader'; export { default as VerticalTab } from './components/vertical-tab'; export { default as Wizard } from './components/wizard'; From f914f7194099c46f93bcd351e58d111d15baeea9 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 14:09:58 +0300 Subject: [PATCH 10/52] refactor: currency issue fixed --- .../transfer-amount-input.scss | 8 +++ .../transfer-amount-input.tsx | 50 +++++++++++++------ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss b/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss index 02a9a8d6bce8..50a5a521d653 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss @@ -8,9 +8,17 @@ } } +.transfer-amount-input-container { + position: relative; +} + .transfer-amount-input { border: none; + position: absolute; line-height: 30px; + display: flex; + flex-shrink: 1; + margin: 0; input { font-size: 20px; diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx index 2be44fa9bce7..710d43c76ca6 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx @@ -2,31 +2,51 @@ import React, { useState } from 'react'; import Input from '../input'; type TTransferAmountInput = { - className?: string; currency: string; + decimalPoints?: number; disabled?: boolean; initialValue?: number; label?: React.ReactNode; + maxDigits: number; }; -const TransferAmountInput = ({ className, currency, disabled = false, initialValue, label }: TTransferAmountInput) => { - const [value, setValue] = useState(0); +const TransferAmountInput = ({ + currency, + decimalPoints = 2, + disabled = false, + initialValue = 0, + label, + maxDigits, +}: TTransferAmountInput) => { + const [value, setValue] = useState(initialValue); + const [focus, setFocus] = useState(false); + + const displayNumber = (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimalPoints }); return (
{label} - { - let input_value = e.target.value; - input_value = input_value.replace(/\D/g, ''); - setValue(Number(input_value) / 100); - }} - type={'text'} - placeholder={`${value.toLocaleString('en-US', { minimumFractionDigits: 2 })} USD`} - value={value.toLocaleString('en-US', { minimumFractionDigits: 2 })} - /> +
+ + setFocus(true)} + onBlur={() => setFocus(false)} + onChange={e => { + const input_value = e.target.value.replace(/\D/g, ''); + if (Number(input_value) <= Math.pow(10, maxDigits)) setValue(Number(input_value) / 100); + }} + type='text' + value={displayNumber(value)} + /> +
); }; From 2d7b9ec4c5126726a2827d1a5c7930273f69450f Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 14:19:20 +0300 Subject: [PATCH 11/52] refactor: tests fix --- .../__tests__/transfer-amount-input.test.tsx | 31 ++++++++++++------- .../transfer-amount-input.tsx | 3 +- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx index 06f05dc08e9b..2dbcaeb662d7 100644 --- a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx +++ b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx @@ -5,21 +5,21 @@ import TransferAmountInput from '../transfer-amount-input'; describe('', () => { it('should render with the initial value of "0.00"', () => { - render(); - const input = screen.getByRole('textbox'); + render(); + const input = screen.getByTestId('dt_transfer-amount-input'); expect(input).toHaveDisplayValue('0.00'); }); it('should not change the value on non-numeric and non-"." inputs', () => { - render(); - const input = screen.getByRole('textbox'); + render(); + const input = screen.getByTestId('dt_transfer-amount-input'); userEvent.type(input, 'abcdef!@#$%^&*()_+-={}[];\'"|\\/,.<>'); expect(input).toHaveDisplayValue('0.00'); }); it('should change the value like an ATM, i.e. from right to left, when entering digits', () => { - render(); - const input = screen.getByRole('textbox'); + render(); + const input = screen.getByTestId('dt_transfer-amount-input'); userEvent.type(input, '1'); expect(input).toHaveDisplayValue('0.01'); userEvent.type(input, '2'); @@ -29,18 +29,25 @@ describe('', () => { }); it('should add commas for big values', () => { - render(); - const input = screen.getByRole('textbox'); - userEvent.type(input, '1234567890'); - expect(input).toHaveDisplayValue('12,345,678.90'); + render(); + const input = screen.getByTestId('dt_transfer-amount-input'); + userEvent.type(input, '12345678'); + expect(input).toHaveDisplayValue('123,456.78'); }); it('should not remove "0.00" when backspacing', () => { - render(); - const input = screen.getByRole('textbox'); + render(); + const input = screen.getByTestId('dt_transfer-amount-input'); userEvent.type(input, '100'); expect(input).toHaveDisplayValue('1.00'); userEvent.clear(input); expect(input).toHaveDisplayValue('0.00'); }); + + it('should not accept more than {maxDigits} digits', () => { + render(); + const input = screen.getByTestId('dt_transfer-amount-input'); + userEvent.type(input, '1234567890987654321'); + expect(input).toHaveDisplayValue('1,234,567.89'); + }); }); diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx index 710d43c76ca6..f4c9715998ed 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx +++ b/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx @@ -29,12 +29,13 @@ const TransferAmountInput = ({
setFocus(true)} From 14defb1a157a02cd5f51c49b8f95d4df17852194 Mon Sep 17 00:00:00 2001 From: Rostik Kayko <119863957+rostislav-deriv@users.noreply.github.com> Date: Wed, 10 May 2023 17:38:18 +0300 Subject: [PATCH 12/52] Update packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx Co-authored-by: George Usynin <103181646+heorhi-deriv@users.noreply.github.com> --- .../__tests__/transfer-amount-input.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx index 2dbcaeb662d7..9d234bed9e1f 100644 --- a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx +++ b/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx @@ -5,7 +5,7 @@ import TransferAmountInput from '../transfer-amount-input'; describe('', () => { it('should render with the initial value of "0.00"', () => { - render(); + render(); const input = screen.getByTestId('dt_transfer-amount-input'); expect(input).toHaveDisplayValue('0.00'); }); From d5bd8a57812af2c446ffb1ce50c644ab0c7a8a00 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 10 May 2023 17:54:45 +0300 Subject: [PATCH 13/52] refactor: TransferAmountInput -> AmountInput --- .../__tests__/amount-input.test.tsx} | 28 +++++++++---------- .../amount-input.scss} | 6 ++-- .../amount-input.tsx} | 20 ++++++------- .../src/components/amount-input/index.ts | 4 +++ .../components/transfer-amount-input/index.ts | 4 --- packages/components/src/index.js | 2 +- 6 files changed, 32 insertions(+), 32 deletions(-) rename packages/components/src/components/{transfer-amount-input/__tests__/transfer-amount-input.test.tsx => amount-input/__tests__/amount-input.test.tsx} (59%) rename packages/components/src/components/{transfer-amount-input/transfer-amount-input.scss => amount-input/amount-input.scss} (79%) rename packages/components/src/components/{transfer-amount-input/transfer-amount-input.tsx => amount-input/amount-input.tsx} (76%) create mode 100644 packages/components/src/components/amount-input/index.ts delete mode 100644 packages/components/src/components/transfer-amount-input/index.ts diff --git a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx similarity index 59% rename from packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx rename to packages/components/src/components/amount-input/__tests__/amount-input.test.tsx index 2dbcaeb662d7..3255c856f2cf 100644 --- a/packages/components/src/components/transfer-amount-input/__tests__/transfer-amount-input.test.tsx +++ b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx @@ -1,25 +1,25 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import TransferAmountInput from '../transfer-amount-input'; +import AmountInput from '../amount-input'; -describe('', () => { +describe('', () => { it('should render with the initial value of "0.00"', () => { - render(); - const input = screen.getByTestId('dt_transfer-amount-input'); + render(); + const input = screen.getByTestId('dt_amount-input'); expect(input).toHaveDisplayValue('0.00'); }); it('should not change the value on non-numeric and non-"." inputs', () => { - render(); - const input = screen.getByTestId('dt_transfer-amount-input'); + render(); + const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, 'abcdef!@#$%^&*()_+-={}[];\'"|\\/,.<>'); expect(input).toHaveDisplayValue('0.00'); }); it('should change the value like an ATM, i.e. from right to left, when entering digits', () => { - render(); - const input = screen.getByTestId('dt_transfer-amount-input'); + render(); + const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '1'); expect(input).toHaveDisplayValue('0.01'); userEvent.type(input, '2'); @@ -29,15 +29,15 @@ describe('', () => { }); it('should add commas for big values', () => { - render(); - const input = screen.getByTestId('dt_transfer-amount-input'); + render(); + const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '12345678'); expect(input).toHaveDisplayValue('123,456.78'); }); it('should not remove "0.00" when backspacing', () => { - render(); - const input = screen.getByTestId('dt_transfer-amount-input'); + render(); + const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '100'); expect(input).toHaveDisplayValue('1.00'); userEvent.clear(input); @@ -45,8 +45,8 @@ describe('', () => { }); it('should not accept more than {maxDigits} digits', () => { - render(); - const input = screen.getByTestId('dt_transfer-amount-input'); + render(); + const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '1234567890987654321'); expect(input).toHaveDisplayValue('1,234,567.89'); }); diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss b/packages/components/src/components/amount-input/amount-input.scss similarity index 79% rename from packages/components/src/components/transfer-amount-input/transfer-amount-input.scss rename to packages/components/src/components/amount-input/amount-input.scss index 50a5a521d653..47a730e70eee 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.scss +++ b/packages/components/src/components/amount-input/amount-input.scss @@ -1,4 +1,4 @@ -.transfer-amount-input-wrapper { +.amount-input-wrapper { display: flex; flex-direction: column; @@ -8,11 +8,11 @@ } } -.transfer-amount-input-container { +.amount-input-container { position: relative; } -.transfer-amount-input { +.amount-input { border: none; position: absolute; line-height: 30px; diff --git a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx similarity index 76% rename from packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx rename to packages/components/src/components/amount-input/amount-input.tsx index f4c9715998ed..26cf26bcc984 100644 --- a/packages/components/src/components/transfer-amount-input/transfer-amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import Input from '../input'; -type TTransferAmountInput = { +type TAmountInput = { currency: string; decimalPoints?: number; disabled?: boolean; @@ -10,32 +10,32 @@ type TTransferAmountInput = { maxDigits: number; }; -const TransferAmountInput = ({ +const AmountInput = ({ currency, decimalPoints = 2, disabled = false, initialValue = 0, label, maxDigits, -}: TTransferAmountInput) => { +}: TAmountInput) => { const [value, setValue] = useState(initialValue); const [focus, setFocus] = useState(false); const displayNumber = (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimalPoints }); return ( -
+
{label} -
+
setFocus(true)} @@ -52,6 +52,6 @@ const TransferAmountInput = ({ ); }; -Input.displayName = 'TransferAmountInput'; +Input.displayName = 'AmountInput'; -export default TransferAmountInput; +export default AmountInput; diff --git a/packages/components/src/components/amount-input/index.ts b/packages/components/src/components/amount-input/index.ts new file mode 100644 index 000000000000..ee447d524403 --- /dev/null +++ b/packages/components/src/components/amount-input/index.ts @@ -0,0 +1,4 @@ +import AmountInput from './amount-input'; +import './amount-input.scss'; + +export default AmountInput; diff --git a/packages/components/src/components/transfer-amount-input/index.ts b/packages/components/src/components/transfer-amount-input/index.ts deleted file mode 100644 index bc5e11d204c1..000000000000 --- a/packages/components/src/components/transfer-amount-input/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import TransferAmountInput from './transfer-amount-input'; -import './transfer-amount-input.scss'; - -export default TransferAmountInput; diff --git a/packages/components/src/index.js b/packages/components/src/index.js index 0dd628370bdb..12ca52ef42de 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -10,6 +10,7 @@ // export default { Label, Button }; export { default as Accordion } from './components/accordion'; +export { default as AmountInput } from './components/amount-input'; export { default as AutoHeightWrapper } from './components/auto-height-wrapper'; export { default as Autocomplete } from './components/autocomplete'; export { default as AutoSizer } from './components/autosizer'; @@ -105,7 +106,6 @@ export { default as TickPicker } from './components/tick-picker'; export { default as TickProgress } from './components/tick-progress'; export { default as Timeline } from './components/timeline'; export { default as Tooltip } from './components/tooltip'; -export { default as TransferAmountInput } from './components/transfer-amount-input'; export { default as UILoader } from './components/u-i-loader'; export { default as VerticalTab } from './components/vertical-tab'; export { default as Wizard } from './components/wizard'; From d9f4107e11e72ea9166ace954d4f76dfcbd6e666 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 11:37:12 +0300 Subject: [PATCH 14/52] refactor: onChange prop added to AmountInput --- .../src/components/amount-input/amount-input.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 26cf26bcc984..ab3844432fdd 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -8,6 +8,7 @@ type TAmountInput = { initialValue?: number; label?: React.ReactNode; maxDigits: number; + onChange?: (value: number) => void; }; const AmountInput = ({ @@ -17,12 +18,21 @@ const AmountInput = ({ initialValue = 0, label, maxDigits, + onChange, }: TAmountInput) => { const [value, setValue] = useState(initialValue); const [focus, setFocus] = useState(false); const displayNumber = (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimalPoints }); + const onChangeHandler = (e: { target: { value: string } }) => { + const input_value = e.target.value.replace(/\D/g, ''); + if (Number(input_value) <= Math.pow(10, maxDigits)) { + setValue(Number(input_value) / 100); + onChange?.(Number(input_value) / 100); + } + }; + return (
{label} @@ -40,10 +50,7 @@ const AmountInput = ({ max_characters={displayNumber(Math.pow(10, maxDigits - 1) / decimalPoints).length} onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} - onChange={e => { - const input_value = e.target.value.replace(/\D/g, ''); - if (Number(input_value) <= Math.pow(10, maxDigits)) setValue(Number(input_value) / 100); - }} + onChange={onChangeHandler} type='text' value={displayNumber(value)} /> From 462fe2c430f48a9cc50ebcf631f5906acb91801d Mon Sep 17 00:00:00 2001 From: Rostik Kayko <119863957+rostislav-deriv@users.noreply.github.com> Date: Thu, 11 May 2023 11:58:05 +0300 Subject: [PATCH 15/52] Update packages/components/src/components/amount-input/amount-input.tsx Co-authored-by: Farzin Mirzaie <72082844+farzin-deriv@users.noreply.github.com> --- .../components/src/components/amount-input/amount-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index ab3844432fdd..8da7aa412abe 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -6,7 +6,7 @@ type TAmountInput = { decimalPoints?: number; disabled?: boolean; initialValue?: number; - label?: React.ReactNode; + label?: string; maxDigits: number; onChange?: (value: number) => void; }; From d7728bcab58625e7e80fc09d9de16e9e7a06597e Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 12:00:11 +0300 Subject: [PATCH 16/52] refactor: suggestions --- .../components/src/components/amount-input/amount-input.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index ab3844432fdd..e233068fc653 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -7,7 +7,7 @@ type TAmountInput = { disabled?: boolean; initialValue?: number; label?: React.ReactNode; - maxDigits: number; + maxDigits?: number; onChange?: (value: number) => void; }; @@ -17,7 +17,7 @@ const AmountInput = ({ disabled = false, initialValue = 0, label, - maxDigits, + maxDigits = 8, onChange, }: TAmountInput) => { const [value, setValue] = useState(initialValue); @@ -59,6 +59,4 @@ const AmountInput = ({ ); }; -Input.displayName = 'AmountInput'; - export default AmountInput; From 10b50b471d581159b57cb15f25f3ff0dab41da0c Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 12:02:32 +0300 Subject: [PATCH 17/52] refactor: suggestions --- .../components/src/components/amount-input/amount-input.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 1ba8666147f2..3bacfbd70b5a 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -17,7 +17,7 @@ const AmountInput = ({ disabled = false, initialValue = 0, label, - maxDigits, + maxDigits = 8, onChange, }: TAmountInput) => { const [value, setValue] = useState(initialValue); @@ -59,6 +59,4 @@ const AmountInput = ({ ); }; -Input.displayName = 'AmountInput'; - export default AmountInput; From fd9b68e4c802bd2fd8d1a93315bef32a7a472b0a Mon Sep 17 00:00:00 2001 From: Rostik Kayko <119863957+rostislav-deriv@users.noreply.github.com> Date: Thu, 11 May 2023 12:12:16 +0300 Subject: [PATCH 18/52] Update packages/components/src/components/amount-input/amount-input.scss Co-authored-by: Farzin Mirzaie <72082844+farzin-deriv@users.noreply.github.com> --- .../components/amount-input/amount-input.scss | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.scss b/packages/components/src/components/amount-input/amount-input.scss index 47a730e70eee..33dd24cf1335 100644 --- a/packages/components/src/components/amount-input/amount-input.scss +++ b/packages/components/src/components/amount-input/amount-input.scss @@ -1,28 +1,30 @@ .amount-input-wrapper { display: flex; flex-direction: column; - - span { - font-size: 14px; - line-height: 20px; - } + padding: 0.8rem; + height: 6.6rem; } .amount-input-container { position: relative; + flex: 1; } .amount-input { - border: none; position: absolute; - line-height: 30px; - display: flex; - flex-shrink: 1; + border: none; + flex: 1; margin: 0; + padding: 0; + height: 100%; + width: 100%; input { - font-size: 20px; - font-weight: 700; - padding: 0; + font-size: var(--text-size-sm); + font-weight: var(--text-weight-bold); + + @include mobile { + font-size: var(--text-size-s); + } } } From 7a0862174d1253ef879b80d632783a05ef3d2a33 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 12:15:40 +0300 Subject: [PATCH 19/52] refactor: props naming --- .../components/amount-input/amount-input.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 3bacfbd70b5a..b39356e790d5 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -3,31 +3,31 @@ import Input from '../input'; type TAmountInput = { currency: string; - decimalPoints?: number; + decimal_points?: number; disabled?: boolean; - initialValue?: number; + initial_value?: number; label?: string; - maxDigits?: number; + max_digits?: number; onChange?: (value: number) => void; }; const AmountInput = ({ currency, - decimalPoints = 2, + decimal_points = 2, disabled = false, - initialValue = 0, + initial_value = 0, label, - maxDigits = 8, + max_digits = 8, onChange, }: TAmountInput) => { - const [value, setValue] = useState(initialValue); + const [value, setValue] = useState(initial_value); const [focus, setFocus] = useState(false); - const displayNumber = (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimalPoints }); + const displayNumber = (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimal_points }); const onChangeHandler = (e: { target: { value: string } }) => { const input_value = e.target.value.replace(/\D/g, ''); - if (Number(input_value) <= Math.pow(10, maxDigits)) { + if (Number(input_value) <= Math.pow(10, max_digits)) { setValue(Number(input_value) / 100); onChange?.(Number(input_value) / 100); } @@ -47,7 +47,7 @@ const AmountInput = ({ className='amount-input' data-testid='dt_amount-input' disabled={disabled} - max_characters={displayNumber(Math.pow(10, maxDigits - 1) / decimalPoints).length} + max_characters={displayNumber(Math.pow(10, max_digits - 1) / decimal_points).length} onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} onChange={onChangeHandler} From 66ded48fcd9dc7d9e0979050faf49338276089b3 Mon Sep 17 00:00:00 2001 From: Rostik Kayko <119863957+rostislav-deriv@users.noreply.github.com> Date: Thu, 11 May 2023 12:32:35 +0300 Subject: [PATCH 20/52] Update packages/components/src/components/amount-input/amount-input.tsx Co-authored-by: Farzin Mirzaie <72082844+farzin-deriv@users.noreply.github.com> --- .../components/src/components/amount-input/amount-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index b39356e790d5..9b720bb87485 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -35,7 +35,7 @@ const AmountInput = ({ return (
- {label} + {label}
Date: Thu, 11 May 2023 12:38:44 +0300 Subject: [PATCH 21/52] fix: import added --- packages/components/src/components/amount-input/amount-input.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 9b720bb87485..3aa5ec5b9f99 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; import Input from '../input'; +import Text from '../text'; type TAmountInput = { currency: string; From 21a0cf546796f3b91c73920f067aca497348d12d Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 12:51:23 +0300 Subject: [PATCH 22/52] refactor: removed redundant Input prop for max_characters --- packages/components/src/components/amount-input/amount-input.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 3aa5ec5b9f99..4ed30ef37095 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -48,7 +48,6 @@ const AmountInput = ({ className='amount-input' data-testid='dt_amount-input' disabled={disabled} - max_characters={displayNumber(Math.pow(10, max_digits - 1) / decimal_points).length} onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} onChange={onChangeHandler} From 676836cfadbb2dbf34cf7081e542a814b8a7f30e Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 13:05:49 +0300 Subject: [PATCH 23/52] refactor: useCallback --- .../src/components/amount-input/amount-input.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 4ed30ef37095..0aca387fdcfc 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import Input from '../input'; import Text from '../text'; @@ -24,7 +24,10 @@ const AmountInput = ({ const [value, setValue] = useState(initial_value); const [focus, setFocus] = useState(false); - const displayNumber = (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimal_points }); + const displayNumber = useCallback( + (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimal_points }), + [decimal_points] + ); const onChangeHandler = (e: { target: { value: string } }) => { const input_value = e.target.value.replace(/\D/g, ''); From cfad24542996ec6b13e37d92e3737e5d97609abf Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 14:50:27 +0300 Subject: [PATCH 24/52] fix: tests and logic as well --- .../__tests__/amount-input.test.tsx | 20 +++++++++++++------ .../components/amount-input/amount-input.tsx | 12 +++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx index 6e7af315d381..69885d10926a 100644 --- a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx +++ b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx @@ -5,20 +5,20 @@ import AmountInput from '../amount-input'; describe('', () => { it('should render with the initial value of "0.00"', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); expect(input).toHaveDisplayValue('0.00'); }); it('should not change the value on non-numeric and non-"." inputs', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, 'abcdef!@#$%^&*()_+-={}[];\'"|\\/,.<>'); expect(input).toHaveDisplayValue('0.00'); }); it('should change the value like an ATM, i.e. from right to left, when entering digits', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '1'); expect(input).toHaveDisplayValue('0.01'); @@ -29,14 +29,14 @@ describe('', () => { }); it('should add commas for big values', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '12345678'); expect(input).toHaveDisplayValue('123,456.78'); }); it('should not remove "0.00" when backspacing', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '100'); expect(input).toHaveDisplayValue('1.00'); @@ -45,9 +45,17 @@ describe('', () => { }); it('should not accept more than {maxDigits} digits', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '1234567890987654321'); expect(input).toHaveDisplayValue('1,234,567.89'); }); + + it('should work correctly with explicitly set {decimal_points}', () => { + render(); + const input = screen.getByTestId('dt_amount-input'); + expect(input).toHaveDisplayValue('0.00000'); + userEvent.type(input, '12345678'); + expect(input).toHaveDisplayValue('123.45678'); + }); }); diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 0aca387fdcfc..ee96f4dc3acd 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -4,7 +4,7 @@ import Text from '../text'; type TAmountInput = { currency: string; - decimal_points?: number; + decimal_places?: number; disabled?: boolean; initial_value?: number; label?: string; @@ -14,7 +14,7 @@ type TAmountInput = { const AmountInput = ({ currency, - decimal_points = 2, + decimal_places = 2, disabled = false, initial_value = 0, label, @@ -25,15 +25,15 @@ const AmountInput = ({ const [focus, setFocus] = useState(false); const displayNumber = useCallback( - (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimal_points }), - [decimal_points] + (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimal_places }), + [decimal_places] ); const onChangeHandler = (e: { target: { value: string } }) => { const input_value = e.target.value.replace(/\D/g, ''); if (Number(input_value) <= Math.pow(10, max_digits)) { - setValue(Number(input_value) / 100); - onChange?.(Number(input_value) / 100); + setValue(Number(input_value) / Math.pow(10, decimal_places)); + onChange?.(Number(input_value) / Math.pow(10, decimal_places)); } }; From 68a9f90ac22b064cb4e9c2041231140db4778850 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 15:20:26 +0300 Subject: [PATCH 25/52] refactor: using isMobile() for responsive design for AmountInput --- .../components/src/components/amount-input/amount-input.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index ee96f4dc3acd..1338fc6e4bb3 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useState } from 'react'; +import { isMobile } from '@deriv/shared'; import Input from '../input'; import Text from '../text'; @@ -39,7 +40,7 @@ const AmountInput = ({ return (
- {label} + {label}
Date: Thu, 11 May 2023 16:35:44 +0300 Subject: [PATCH 26/52] refactor: toLocaleString locale changed to `undefined` --- .../components/src/components/amount-input/amount-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 1338fc6e4bb3..78de63335a76 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -26,7 +26,7 @@ const AmountInput = ({ const [focus, setFocus] = useState(false); const displayNumber = useCallback( - (number: number) => number.toLocaleString('en-US', { minimumFractionDigits: decimal_places }), + (number: number) => number.toLocaleString(undefined, { minimumFractionDigits: decimal_places }), [decimal_places] ); From 37b4ac35ce9b592c2bc6584f57252ab24a72ea01 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 11 May 2023 17:54:49 +0300 Subject: [PATCH 27/52] refactor: test From bf1107c95f9b015463b6611d8af499908e1a3f57 Mon Sep 17 00:00:00 2001 From: Rostik Kayko <119863957+rostislav-deriv@users.noreply.github.com> Date: Fri, 12 May 2023 11:02:18 +0300 Subject: [PATCH 28/52] Update packages/components/src/components/amount-input/amount-input.tsx Co-authored-by: Farzin Mirzaie <72082844+farzin-deriv@users.noreply.github.com> --- .../components/src/components/amount-input/amount-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 78de63335a76..a39caa8dbf1a 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -30,7 +30,7 @@ const AmountInput = ({ [decimal_places] ); - const onChangeHandler = (e: { target: { value: string } }) => { + const onChangeHandler: React.ComponentProps['onChange'] = e => { const input_value = e.target.value.replace(/\D/g, ''); if (Number(input_value) <= Math.pow(10, max_digits)) { setValue(Number(input_value) / Math.pow(10, decimal_places)); From f3eb394544ccd580e9ca1e6fcec04f12a7d0d5e0 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Fri, 12 May 2023 12:14:02 +0300 Subject: [PATCH 29/52] feat: amount-input-for-testing.tsx --- .../amount-input-for-testing.tsx | 23 +++++++++++++++++++ .../src/modules/traders-hub/index.tsx | 2 ++ 2 files changed, 25 insertions(+) create mode 100644 packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx diff --git a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx new file mode 100644 index 000000000000..9110ef019ba1 --- /dev/null +++ b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { AmountInput } from '@deriv/components'; + +const AmountInputForTesting = () => { + return ( +
+ +
+ ); +}; + +export default AmountInputForTesting; diff --git a/packages/appstore/src/modules/traders-hub/index.tsx b/packages/appstore/src/modules/traders-hub/index.tsx index d4b0cfb83fb1..d4e0a4b7b09c 100644 --- a/packages/appstore/src/modules/traders-hub/index.tsx +++ b/packages/appstore/src/modules/traders-hub/index.tsx @@ -13,6 +13,7 @@ import { Localize } from '@deriv/translations'; import classNames from 'classnames'; import WalletsBanner from 'Components/wallets-banner'; import './traders-hub.scss'; +import AmountInputForTesting from '../../components/modals/amount-input-for-testing/amount-input-for-testing'; const TradersHub = () => { const { traders_hub, client, ui } = useStores(); @@ -84,6 +85,7 @@ const TradersHub = () => { > {can_show_notify && }
+ From 9b78680e97739daeef198ab02737c5717a1e6319 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Fri, 12 May 2023 12:39:08 +0300 Subject: [PATCH 30/52] fix: amount-input-for-testing.tsx --- .../amount-input-for-testing/amount-input-for-testing.tsx | 5 ----- packages/appstore/src/modules/traders-hub/index.tsx | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx index 9110ef019ba1..91dc45c685c6 100644 --- a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx +++ b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx @@ -5,12 +5,7 @@ const AmountInputForTesting = () => { return (
{ > {can_show_notify && }
-
+
@@ -110,6 +110,7 @@ const TradersHub = () => { )} {selected_platform_type === 'options' && } {selected_platform_type === 'cfd' && } + {scrolled && } From d960fd25e44164fd7dafa71aa1984e80899af746 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Fri, 12 May 2023 12:44:19 +0300 Subject: [PATCH 31/52] fix: amount-input-for-testing.tsx --- .../modals/amount-input-for-testing/amount-input-for-testing.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx index 91dc45c685c6..d32c9e640678 100644 --- a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx +++ b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx @@ -5,7 +5,6 @@ const AmountInputForTesting = () => { return (
Date: Fri, 12 May 2023 12:53:39 +0300 Subject: [PATCH 32/52] Update packages/components/src/components/amount-input/amount-input.tsx Co-authored-by: Farzin Mirzaie <72082844+farzin-deriv@users.noreply.github.com> --- .../src/components/amount-input/amount-input.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index a39caa8dbf1a..b64cf2df4906 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -31,11 +31,14 @@ const AmountInput = ({ ); const onChangeHandler: React.ComponentProps['onChange'] = e => { - const input_value = e.target.value.replace(/\D/g, ''); - if (Number(input_value) <= Math.pow(10, max_digits)) { - setValue(Number(input_value) / Math.pow(10, decimal_places)); - onChange?.(Number(input_value) / Math.pow(10, decimal_places)); - } + const input = e.target.value.replace(/[^\d.]/g, ''); + const input_digits_length = input.replaceAll('.', ''); + const has_reached_max_digits = input_digits_length.length > max_digits; + + if (has_reached_max_digits) return; + + setValue(Number(input)); + onChange?.(Number(input)); }; return ( From fd936832999519c1f1b3e0c4cde829cda6b04d82 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Fri, 12 May 2023 13:46:54 +0300 Subject: [PATCH 33/52] fix: tests fix by rollback --- .../src/components/amount-input/amount-input.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index b64cf2df4906..a39caa8dbf1a 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -31,14 +31,11 @@ const AmountInput = ({ ); const onChangeHandler: React.ComponentProps['onChange'] = e => { - const input = e.target.value.replace(/[^\d.]/g, ''); - const input_digits_length = input.replaceAll('.', ''); - const has_reached_max_digits = input_digits_length.length > max_digits; - - if (has_reached_max_digits) return; - - setValue(Number(input)); - onChange?.(Number(input)); + const input_value = e.target.value.replace(/\D/g, ''); + if (Number(input_value) <= Math.pow(10, max_digits)) { + setValue(Number(input_value) / Math.pow(10, decimal_places)); + onChange?.(Number(input_value) / Math.pow(10, decimal_places)); + } }; return ( From 9254d04585ea7b2092b19c12b65bb2d17a49f9da Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Fri, 12 May 2023 17:40:37 +0300 Subject: [PATCH 34/52] refactor: cursor/caret issue resolved --- .../components/amount-input/amount-input.tsx | 18 ++++++++++++++++-- .../components/src/components/input/input.tsx | 12 ++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index a39caa8dbf1a..046a9055b78f 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from 'react'; +import React, { KeyboardEventHandler, useCallback, useState } from 'react'; import { isMobile } from '@deriv/shared'; import Input from '../input'; import Text from '../text'; @@ -9,6 +9,7 @@ type TAmountInput = { disabled?: boolean; initial_value?: number; label?: string; + locale?: Intl.LocalesArgument; max_digits?: number; onChange?: (value: number) => void; }; @@ -19,6 +20,7 @@ const AmountInput = ({ disabled = false, initial_value = 0, label, + locale, max_digits = 8, onChange, }: TAmountInput) => { @@ -26,7 +28,7 @@ const AmountInput = ({ const [focus, setFocus] = useState(false); const displayNumber = useCallback( - (number: number) => number.toLocaleString(undefined, { minimumFractionDigits: decimal_places }), + (number: number) => number.toLocaleString(locale, { minimumFractionDigits: decimal_places }), [decimal_places] ); @@ -38,6 +40,16 @@ const AmountInput = ({ } }; + const onMouseDownHandler: React.ComponentProps['onMouseDown'] = e => { + e.preventDefault(); + e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length); + e.currentTarget.focus(); + }; + + const onKeyDownHandler: KeyboardEventHandler = e => { + if (e.code.startsWith('Arrow')) e.preventDefault(); + }; + return (
{label} @@ -55,6 +67,8 @@ const AmountInput = ({ onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} onChange={onChangeHandler} + onMouseDown={onMouseDownHandler} + onKeyDown={onKeyDownHandler} type='text' value={displayNumber(value)} /> diff --git a/packages/components/src/components/input/input.tsx b/packages/components/src/components/input/input.tsx index 92f79cbbb3e1..0af547ce60e5 100644 --- a/packages/components/src/components/input/input.tsx +++ b/packages/components/src/components/input/input.tsx @@ -26,10 +26,12 @@ export type TInputProps = { max_characters?: number; maxLength?: number; name?: string; - onBlur?: (e: React.FocusEvent) => void; - onChange?: (e: React.ChangeEvent) => void; - onFocus?: (e: React.FocusEvent) => void; - onPaste?: (e: React.ClipboardEvent) => void; + onBlur?: React.FocusEventHandler; + onChange?: React.ChangeEventHandler; + onMouseDown?: React.MouseEventHandler; + onFocus?: React.FocusEventHandler; + onKeyDown?: React.KeyboardEventHandler; + onPaste?: React.ClipboardEventHandler; placeholder?: string; required?: boolean; trailing_icon?: React.ReactElement; @@ -137,6 +139,8 @@ const Input = React.forwardRef Date: Fri, 12 May 2023 18:42:26 +0300 Subject: [PATCH 35/52] refactor: pasting behavior resolved --- .../components/amount-input/amount-input.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 046a9055b78f..52f4de211221 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -26,18 +26,24 @@ const AmountInput = ({ }: TAmountInput) => { const [value, setValue] = useState(initial_value); const [focus, setFocus] = useState(false); + const [isPasting, setIsPasting] = useState(false); const displayNumber = useCallback( (number: number) => number.toLocaleString(locale, { minimumFractionDigits: decimal_places }), - [decimal_places] + [decimal_places, locale] ); const onChangeHandler: React.ComponentProps['onChange'] = e => { - const input_value = e.target.value.replace(/\D/g, ''); + const input_value = e.target.value.replace(/\D/g, '').replace(/^0+/, ''); + let newValue = value; if (Number(input_value) <= Math.pow(10, max_digits)) { - setValue(Number(input_value) / Math.pow(10, decimal_places)); - onChange?.(Number(input_value) / Math.pow(10, decimal_places)); + newValue = Number(input_value) / Math.pow(10, decimal_places); + } else if (isPasting && value === 0) { + newValue = Number(input_value.substring(0, max_digits)) / Math.pow(10, decimal_places); } + setValue(newValue); + onChange?.(newValue); + setIsPasting(false); }; const onMouseDownHandler: React.ComponentProps['onMouseDown'] = e => { @@ -67,8 +73,9 @@ const AmountInput = ({ onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} onChange={onChangeHandler} - onMouseDown={onMouseDownHandler} onKeyDown={onKeyDownHandler} + onMouseDown={onMouseDownHandler} + onPaste={() => setIsPasting(true)} type='text' value={displayNumber(value)} /> From cfaaebdef8ed21d15ba6b2a1dd8fc80c643e1be6 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Sat, 13 May 2023 12:24:15 +0300 Subject: [PATCH 36/52] refactor: separators on paste should remain now --- .../src/components/amount-input/amount-input.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 52f4de211221..676e67d1b4a2 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -34,12 +34,15 @@ const AmountInput = ({ ); const onChangeHandler: React.ComponentProps['onChange'] = e => { - const input_value = e.target.value.replace(/\D/g, '').replace(/^0+/, ''); + const input_value = e.target.value + .replace(/[^\d.,]/g, '') + .replace(/[,.](?=.*[,.])/g, '') + .replace(/^0+/g, ''); let newValue = value; - if (Number(input_value) <= Math.pow(10, max_digits)) { - newValue = Number(input_value) / Math.pow(10, decimal_places); + if (input_value.replace(/[.,]/g, '').length <= max_digits) { + newValue = Number(input_value.replace(',', '.')); } else if (isPasting && value === 0) { - newValue = Number(input_value.substring(0, max_digits)) / Math.pow(10, decimal_places); + newValue = Number(input_value.replace(',', '.').substring(0, max_digits)); } setValue(newValue); onChange?.(newValue); From 1ce7ef1f1fb5b5e04a837e181e129eec73313f34 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Sat, 13 May 2023 14:43:40 +0300 Subject: [PATCH 37/52] fix: fixed the behaviour except ctrl + a; added comments --- .../components/amount-input/amount-input.tsx | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 676e67d1b4a2..b39739c89f6d 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -34,16 +34,28 @@ const AmountInput = ({ ); const onChangeHandler: React.ComponentProps['onChange'] = e => { - const input_value = e.target.value - .replace(/[^\d.,]/g, '') - .replace(/[,.](?=.*[,.])/g, '') - .replace(/^0+/g, ''); + // remove all characters that are not digit / point / comma: + const input_value = e.target.value.replace(/[^\d.,]/g, ''); let newValue = value; - if (input_value.replace(/[.,]/g, '').length <= max_digits) { - newValue = Number(input_value.replace(',', '.')); - } else if (isPasting && value === 0) { - newValue = Number(input_value.replace(',', '.').substring(0, max_digits)); + if (!isPasting) { + // handle ATM typing: + if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) + newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); + } else { + // handle pasting: + const pasted_string = input_value.substring(displayNumber(value).length); + // get the presumable thing the user want to paste: + const pasted_value = pasted_string.replace(/[,.](?=.*[,.])/g, '').replace(',', '.'); + if (!pasted_value) return; + if (value === 0) { + // handle pasting when there's nothing entered before it: + newValue = Number(pasted_value.substring(0, pasted_value.includes('.') ? max_digits + 1 : max_digits)); + } else if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) { + // handle pasting when there's something entered before it and there's space for the pasted value: + newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); + } } + setValue(newValue); onChange?.(newValue); setIsPasting(false); From e6a118ec24dce2515893b382623b90aeb0b9a654 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Sat, 13 May 2023 14:53:30 +0300 Subject: [PATCH 38/52] refactor: isPasting -> is_pasting --- .../components/src/components/amount-input/amount-input.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index b39739c89f6d..527b63007c24 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -26,7 +26,7 @@ const AmountInput = ({ }: TAmountInput) => { const [value, setValue] = useState(initial_value); const [focus, setFocus] = useState(false); - const [isPasting, setIsPasting] = useState(false); + const [is_pasting, setIsPasting] = useState(false); const displayNumber = useCallback( (number: number) => number.toLocaleString(locale, { minimumFractionDigits: decimal_places }), @@ -37,7 +37,7 @@ const AmountInput = ({ // remove all characters that are not digit / point / comma: const input_value = e.target.value.replace(/[^\d.,]/g, ''); let newValue = value; - if (!isPasting) { + if (!is_pasting) { // handle ATM typing: if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); From 431e8d4a76125b602cd0fb08e94033f602549cde Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Sat, 13 May 2023 16:10:47 +0300 Subject: [PATCH 39/52] fix: all behaviour seems to be as expected now --- .../src/components/amount-input/amount-input.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 527b63007c24..19c4caa8f520 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -27,6 +27,7 @@ const AmountInput = ({ const [value, setValue] = useState(initial_value); const [focus, setFocus] = useState(false); const [is_pasting, setIsPasting] = useState(false); + const [is_fully_selected, setIsFullySelected] = useState(false); const displayNumber = useCallback( (number: number) => number.toLocaleString(locale, { minimumFractionDigits: decimal_places }), @@ -43,31 +44,33 @@ const AmountInput = ({ newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); } else { // handle pasting: - const pasted_string = input_value.substring(displayNumber(value).length); - // get the presumable thing the user want to paste: + const pasted_string = is_fully_selected ? input_value : input_value.substring(displayNumber(value).length); + // understand the thing the user want to paste: const pasted_value = pasted_string.replace(/[,.](?=.*[,.])/g, '').replace(',', '.'); - if (!pasted_value) return; - if (value === 0) { - // handle pasting when there's nothing entered before it: + if (value === 0 || is_fully_selected) { + // handle pasting when there's nothing entered before it, or it is overridden: newValue = Number(pasted_value.substring(0, pasted_value.includes('.') ? max_digits + 1 : max_digits)); } else if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) { // handle pasting when there's something entered before it and there's space for the pasted value: newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); } } - setValue(newValue); onChange?.(newValue); setIsPasting(false); + setIsFullySelected(false); }; const onMouseDownHandler: React.ComponentProps['onMouseDown'] = e => { e.preventDefault(); e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length); e.currentTarget.focus(); + setIsFullySelected(false); }; const onKeyDownHandler: KeyboardEventHandler = e => { + if (e.currentTarget.selectionStart === 0 && e.currentTarget.selectionEnd === displayNumber(value).length) + setIsFullySelected(true); if (e.code.startsWith('Arrow')) e.preventDefault(); }; From c339fd566a48052fdd104c7cacfe26287f23bdda Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Sat, 13 May 2023 17:25:00 +0300 Subject: [PATCH 40/52] test: added more tests --- .../__tests__/amount-input.test.tsx | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx index 69885d10926a..c69190ebbfdb 100644 --- a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx +++ b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx @@ -4,12 +4,18 @@ import userEvent from '@testing-library/user-event'; import AmountInput from '../amount-input'; describe('', () => { - it('should render with the initial value of "0.00"', () => { - render(); + it('should render with the initial value of "0.00" if {initial_value} is not specified', () => { + render(); const input = screen.getByTestId('dt_amount-input'); expect(input).toHaveDisplayValue('0.00'); }); + it('should render with the correct initial value if {initial_value} was supplied', () => { + render(); + const input = screen.getByTestId('dt_amount-input'); + expect(input).toHaveDisplayValue('42.00'); + }); + it('should not change the value on non-numeric and non-"." inputs', () => { render(); const input = screen.getByTestId('dt_amount-input'); @@ -29,10 +35,10 @@ describe('', () => { }); it('should add commas for big values', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); - userEvent.type(input, '12345678'); - expect(input).toHaveDisplayValue('123,456.78'); + userEvent.type(input, '123456789'); + expect(input).toHaveDisplayValue('1,234,567.89'); }); it('should not remove "0.00" when backspacing', () => { @@ -58,4 +64,20 @@ describe('', () => { userEvent.type(input, '12345678'); expect(input).toHaveDisplayValue('123.45678'); }); + + it('should allow pasting numbers and then interpret those correctly', () => { + render(); + const input = screen.getByTestId('dt_amount-input'); + const values = [ + ['123', '123.00'], + ['123.42', '123.42'], + ['123,42', '123.42'], + ['123,000.00', '123,000.00'], + ]; + values.forEach(pair => { + userEvent.clear(input); + userEvent.paste(input, pair[0]); + expect(input).toHaveDisplayValue(pair[1]); + }); + }); }); From ddb5f56e18de4abf589e17f543f6e640cc0b1022 Mon Sep 17 00:00:00 2001 From: Rostik Kayko <119863957+rostislav-deriv@users.noreply.github.com> Date: Tue, 16 May 2023 16:32:25 +0300 Subject: [PATCH 41/52] refactor: input type changed to number --- .../components/src/components/amount-input/amount-input.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 19c4caa8f520..b6e007b84362 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -81,7 +81,7 @@ const AmountInput = ({ setIsPasting(true)} - type='text' + type='number' value={displayNumber(value)} />
From 65ee80f4b4e2d7948e331c6a7921554a6073fdda Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Tue, 16 May 2023 17:57:38 +0300 Subject: [PATCH 42/52] refactor: minor tests changes; also inputMode added to force keyboard on mobiles to be numeric --- .../amount-input/__tests__/amount-input.test.tsx | 8 ++++---- .../src/components/amount-input/amount-input.tsx | 6 ++++-- packages/components/src/components/input/input.tsx | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx index c69190ebbfdb..76d096937ea2 100644 --- a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx +++ b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx @@ -11,20 +11,20 @@ describe('', () => { }); it('should render with the correct initial value if {initial_value} was supplied', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); expect(input).toHaveDisplayValue('42.00'); }); it('should not change the value on non-numeric and non-"." inputs', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, 'abcdef!@#$%^&*()_+-={}[];\'"|\\/,.<>'); expect(input).toHaveDisplayValue('0.00'); }); it('should change the value like an ATM, i.e. from right to left, when entering digits', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '1'); expect(input).toHaveDisplayValue('0.01'); @@ -42,7 +42,7 @@ describe('', () => { }); it('should not remove "0.00" when backspacing', () => { - render(); + render(); const input = screen.getByTestId('dt_amount-input'); userEvent.type(input, '100'); expect(input).toHaveDisplayValue('1.00'); diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index b6e007b84362..d0b19a9e4f4a 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -81,7 +81,8 @@ const AmountInput = ({ setIsPasting(true)} - type='number' + type='text' + inputMode='numeric' value={displayNumber(value)} />
diff --git a/packages/components/src/components/input/input.tsx b/packages/components/src/components/input/input.tsx index 0af547ce60e5..9d8693a5bd79 100644 --- a/packages/components/src/components/input/input.tsx +++ b/packages/components/src/components/input/input.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames'; -import React from 'react'; +import React, { HTMLAttributes } from 'react'; import Field from '../field'; import Text from '../text/text'; @@ -18,6 +18,7 @@ export type TInputProps = { hint?: React.ReactNode; id?: string; initial_character_count?: number; + inputMode?: HTMLAttributes['inputMode']; input_id?: string; is_relative_hint?: boolean; label_className?: string; From 0f8ecf45ab05a0817816956710c121731ca27e77 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 17 May 2023 02:36:27 +0300 Subject: [PATCH 43/52] refactor: toggles --- .../amount-input-for-testing.tsx | 70 ++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx index d32c9e640678..9f0fc6298c3d 100644 --- a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx +++ b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx @@ -1,15 +1,81 @@ -import React from 'react'; +import React, { useState } from 'react'; import { AmountInput } from '@deriv/components'; const AmountInputForTesting = () => { + const [currency, setCurrency] = useState('USD'); + const [disabled, setDisabled] = useState(false); + const [max_digits, setMaxDigits] = useState(8); + const [decimal_points, setDecimalPoints] = useState(2); + return (
- +
+ Currency: + setCurrency(e.target.value)} /> +
+
+ Disabled: + setDisabled(!disabled)} /> +
+
+ Max digits: + setMaxDigits(+e.target.value)} + /> +
+
+ Decimal points: + setDecimalPoints(+e.target.value)} + /> +
+
); }; From 6d47160577effbd8e5150e0036ecbf284f5646ba Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Wed, 17 May 2023 16:18:12 +0300 Subject: [PATCH 44/52] refactor: cursor/caret fix using state --- .../components/amount-input/amount-input.tsx | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index d0b19a9e4f4a..ad32f05620cd 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -1,4 +1,4 @@ -import React, { KeyboardEventHandler, useCallback, useState } from 'react'; +import React, { KeyboardEventHandler, useCallback, useEffect, useState } from 'react'; import { isMobile } from '@deriv/shared'; import Input from '../input'; import Text from '../text'; @@ -28,13 +28,24 @@ const AmountInput = ({ const [focus, setFocus] = useState(false); const [is_pasting, setIsPasting] = useState(false); const [is_fully_selected, setIsFullySelected] = useState(false); + const [caret_position, setCaretPosition] = useState(0); + const [target, setTarget] = useState['target']>(); const displayNumber = useCallback( (number: number) => number.toLocaleString(locale, { minimumFractionDigits: decimal_places }), [decimal_places, locale] ); + useEffect(() => { + // update caret position every time the value changes (this happens after onChange) + target?.setSelectionRange( + displayNumber(value).length - caret_position, + displayNumber(value).length - caret_position + ); + }, [value]); + const onChangeHandler: React.ComponentProps['onChange'] = e => { + if (!target) setTarget(e.target); // remove all characters that are not digit / point / comma: const input_value = e.target.value.replace(/[^\d.,]/g, ''); let newValue = value; @@ -62,16 +73,15 @@ const AmountInput = ({ }; const onMouseDownHandler: React.ComponentProps['onMouseDown'] = e => { - e.preventDefault(); - e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length); - e.currentTarget.focus(); - setIsFullySelected(false); + if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { + setCaretPosition(e.currentTarget.value.length - e.currentTarget.selectionEnd); + } }; const onKeyDownHandler: KeyboardEventHandler = e => { - if (e.currentTarget.selectionStart === 0 && e.currentTarget.selectionEnd === displayNumber(value).length) - setIsFullySelected(true); - if (e.code.startsWith('Arrow')) e.preventDefault(); + if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { + setCaretPosition(e.currentTarget.value.length - e.currentTarget.selectionEnd); + } }; return ( From 70ead4cc7006231836e1dfe16f0c022237ef3f4a Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 18 May 2023 10:01:03 +0300 Subject: [PATCH 45/52] fix: wring pasting behaviour fixed --- .../components/amount-input/amount-input.tsx | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index ad32f05620cd..a5b984d88fe8 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -27,8 +27,11 @@ const AmountInput = ({ const [value, setValue] = useState(initial_value); const [focus, setFocus] = useState(false); const [is_pasting, setIsPasting] = useState(false); - const [is_fully_selected, setIsFullySelected] = useState(false); const [caret_position, setCaretPosition] = useState(0); + const [selection, setSelection] = useState<{ + selectionStart: number; + selectionEnd: number; + }>({ selectionStart: 0, selectionEnd: 0 }); const [target, setTarget] = useState['target']>(); const displayNumber = useCallback( @@ -38,27 +41,36 @@ const AmountInput = ({ useEffect(() => { // update caret position every time the value changes (this happens after onChange) - target?.setSelectionRange( - displayNumber(value).length - caret_position, - displayNumber(value).length - caret_position - ); + const updated_caret_position = displayNumber(value).length - caret_position; + target?.setSelectionRange(updated_caret_position, updated_caret_position); + setSelection({ selectionStart: updated_caret_position, selectionEnd: updated_caret_position }); }, [value]); const onChangeHandler: React.ComponentProps['onChange'] = e => { if (!target) setTarget(e.target); - // remove all characters that are not digit / point / comma: - const input_value = e.target.value.replace(/[^\d.,]/g, ''); let newValue = value; if (!is_pasting) { + // remove all characters that are not digit / point / comma: + const input_value = e.target.value.replace(/[^\d.,]/g, ''); // handle ATM typing: if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); } else { // handle pasting: - const pasted_string = is_fully_selected ? input_value : input_value.substring(displayNumber(value).length); - // understand the thing the user want to paste: - const pasted_value = pasted_string.replace(/[,.](?=.*[,.])/g, '').replace(',', '.'); - if (value === 0 || is_fully_selected) { + const selection_length = selection.selectionEnd - selection.selectionStart; + const pasted_string_length = e.target.value.length - selection_length - displayNumber(value).length; + const pasted_string = e.target.value.substring( + selection.selectionStart, + selection.selectionStart + pasted_string_length + ); + // remove all characters that are not digit / point / comma: + const input_value = e.target.value.replace(/[^\d.,]/g, ''); + // understand the thing user wants to paste: + const pasted_value = pasted_string + .replace(/[^\d.,]/g, '') + .replace(/[,.](?=.*[,.])/g, '') + .replace(',', '.'); + if ((value === 0 && caret_position === 0) || selection_length === displayNumber(value).length) { // handle pasting when there's nothing entered before it, or it is overridden: newValue = Number(pasted_value.substring(0, pasted_value.includes('.') ? max_digits + 1 : max_digits)); } else if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) { @@ -67,20 +79,27 @@ const AmountInput = ({ } } setValue(newValue); - onChange?.(newValue); setIsPasting(false); - setIsFullySelected(false); + onChange?.(newValue); }; const onMouseDownHandler: React.ComponentProps['onMouseDown'] = e => { if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { setCaretPosition(e.currentTarget.value.length - e.currentTarget.selectionEnd); + setSelection({ + selectionStart: e.currentTarget.selectionStart, + selectionEnd: e.currentTarget.selectionEnd, + }); } }; const onKeyDownHandler: KeyboardEventHandler = e => { if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { setCaretPosition(e.currentTarget.value.length - e.currentTarget.selectionEnd); + setSelection({ + selectionStart: e.currentTarget.selectionStart, + selectionEnd: e.currentTarget.selectionEnd, + }); } }; From d8be5875b61ded66bfe95815b7881d727acebbe1 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 18 May 2023 10:07:13 +0300 Subject: [PATCH 46/52] refactor: naming change for clarity --- .../src/components/amount-input/amount-input.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index a5b984d88fe8..e5a895f47e07 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -27,7 +27,7 @@ const AmountInput = ({ const [value, setValue] = useState(initial_value); const [focus, setFocus] = useState(false); const [is_pasting, setIsPasting] = useState(false); - const [caret_position, setCaretPosition] = useState(0); + const [caret_right_offset, setCaretRightOffset] = useState(0); const [selection, setSelection] = useState<{ selectionStart: number; selectionEnd: number; @@ -41,7 +41,7 @@ const AmountInput = ({ useEffect(() => { // update caret position every time the value changes (this happens after onChange) - const updated_caret_position = displayNumber(value).length - caret_position; + const updated_caret_position = displayNumber(value).length - caret_right_offset; target?.setSelectionRange(updated_caret_position, updated_caret_position); setSelection({ selectionStart: updated_caret_position, selectionEnd: updated_caret_position }); }, [value]); @@ -70,7 +70,7 @@ const AmountInput = ({ .replace(/[^\d.,]/g, '') .replace(/[,.](?=.*[,.])/g, '') .replace(',', '.'); - if ((value === 0 && caret_position === 0) || selection_length === displayNumber(value).length) { + if ((value === 0 && caret_right_offset === 0) || selection_length === displayNumber(value).length) { // handle pasting when there's nothing entered before it, or it is overridden: newValue = Number(pasted_value.substring(0, pasted_value.includes('.') ? max_digits + 1 : max_digits)); } else if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) { @@ -85,7 +85,7 @@ const AmountInput = ({ const onMouseDownHandler: React.ComponentProps['onMouseDown'] = e => { if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { - setCaretPosition(e.currentTarget.value.length - e.currentTarget.selectionEnd); + setCaretRightOffset(e.currentTarget.value.length - e.currentTarget.selectionEnd); setSelection({ selectionStart: e.currentTarget.selectionStart, selectionEnd: e.currentTarget.selectionEnd, @@ -95,7 +95,7 @@ const AmountInput = ({ const onKeyDownHandler: KeyboardEventHandler = e => { if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { - setCaretPosition(e.currentTarget.value.length - e.currentTarget.selectionEnd); + setCaretRightOffset(e.currentTarget.value.length - e.currentTarget.selectionEnd); setSelection({ selectionStart: e.currentTarget.selectionStart, selectionEnd: e.currentTarget.selectionEnd, From a778bc0f03d0775ea6ed4992e323f91c68822b11 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 18 May 2023 10:57:40 +0300 Subject: [PATCH 47/52] refactor: added a handler and comments --- .../components/amount-input/amount-input.tsx | 51 ++++++++++--------- .../components/src/components/input/input.tsx | 2 + 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index e5a895f47e07..6c1de260e0f0 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -1,4 +1,4 @@ -import React, { KeyboardEventHandler, useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { isMobile } from '@deriv/shared'; import Input from '../input'; import Text from '../text'; @@ -50,9 +50,9 @@ const AmountInput = ({ if (!target) setTarget(e.target); let newValue = value; if (!is_pasting) { + // handle ATM typing: // remove all characters that are not digit / point / comma: const input_value = e.target.value.replace(/[^\d.,]/g, ''); - // handle ATM typing: if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); } else { @@ -65,17 +65,25 @@ const AmountInput = ({ ); // remove all characters that are not digit / point / comma: const input_value = e.target.value.replace(/[^\d.,]/g, ''); - // understand the thing user wants to paste: + // understand the value user wants to paste: const pasted_value = pasted_string - .replace(/[^\d.,]/g, '') - .replace(/[,.](?=.*[,.])/g, '') - .replace(',', '.'); - if ((value === 0 && caret_right_offset === 0) || selection_length === displayNumber(value).length) { - // handle pasting when there's nothing entered before it, or it is overridden: - newValue = Number(pasted_value.substring(0, pasted_value.includes('.') ? max_digits + 1 : max_digits)); - } else if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) { - // handle pasting when there's something entered before it and there's space for the pasted value: - newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); + .replace(/[^\d.,]/g, '') // remove all characters that are not digit / point / comma + .replace(/[,.](?=.*[,.])/g, '') // leave only the last point / comma + .replace(',', '.'); // make the last point / comma separator a point + if (pasted_value.replace('.', '')) { + // if the value is a valid non-empty string, handle the two scenarios: + if ((value === 0 && caret_right_offset === 0) || selection_length === displayNumber(value).length) { + // handle pasting when there's nothing entered before it, or it is overridden (intention: reset value): + newValue = Number( + pasted_value.substring( + 0, + pasted_value.includes('.') ? max_digits + 1 : max_digits - decimal_places + ) + ); + } else if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) { + // handle pasting when there's something entered before it and there's space for the pasted value (intention: add to value): + newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); + } } } setValue(newValue); @@ -83,17 +91,9 @@ const AmountInput = ({ onChange?.(newValue); }; - const onMouseDownHandler: React.ComponentProps['onMouseDown'] = e => { - if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { - setCaretRightOffset(e.currentTarget.value.length - e.currentTarget.selectionEnd); - setSelection({ - selectionStart: e.currentTarget.selectionStart, - selectionEnd: e.currentTarget.selectionEnd, - }); - } - }; - - const onKeyDownHandler: KeyboardEventHandler = e => { + const inputActionHandler = (e: { + currentTarget: { value: string; selectionStart: number | null; selectionEnd: number | null }; + }) => { if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { setCaretRightOffset(e.currentTarget.value.length - e.currentTarget.selectionEnd); setSelection({ @@ -121,8 +121,9 @@ const AmountInput = ({ onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} onChange={onChangeHandler} - onKeyDown={onKeyDownHandler} - onMouseDown={onMouseDownHandler} + onKeyDown={inputActionHandler} + onMouseDown={inputActionHandler} + onMouseUp={inputActionHandler} onPaste={() => setIsPasting(true)} type='text' inputMode='numeric' diff --git a/packages/components/src/components/input/input.tsx b/packages/components/src/components/input/input.tsx index 9d8693a5bd79..af1379d6c24b 100644 --- a/packages/components/src/components/input/input.tsx +++ b/packages/components/src/components/input/input.tsx @@ -30,6 +30,7 @@ export type TInputProps = { onBlur?: React.FocusEventHandler; onChange?: React.ChangeEventHandler; onMouseDown?: React.MouseEventHandler; + onMouseUp?: React.MouseEventHandler; onFocus?: React.FocusEventHandler; onKeyDown?: React.KeyboardEventHandler; onPaste?: React.ClipboardEventHandler; @@ -142,6 +143,7 @@ const Input = React.forwardRef Date: Thu, 18 May 2023 11:37:11 +0300 Subject: [PATCH 48/52] fix: tests and a logical flaw --- .../src/components/amount-input/__tests__/amount-input.test.tsx | 1 + .../components/src/components/amount-input/amount-input.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx index 76d096937ea2..29d8b6a8d27c 100644 --- a/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx +++ b/packages/components/src/components/amount-input/__tests__/amount-input.test.tsx @@ -76,6 +76,7 @@ describe('', () => { ]; values.forEach(pair => { userEvent.clear(input); + userEvent.click(input); userEvent.paste(input, pair[0]); expect(input).toHaveDisplayValue(pair[1]); }); diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 6c1de260e0f0..6ef636729483 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -58,7 +58,7 @@ const AmountInput = ({ } else { // handle pasting: const selection_length = selection.selectionEnd - selection.selectionStart; - const pasted_string_length = e.target.value.length - selection_length - displayNumber(value).length; + const pasted_string_length = e.target.value.length + selection_length - displayNumber(value).length; const pasted_string = e.target.value.substring( selection.selectionStart, selection.selectionStart + pasted_string_length From 98ad866f3de09269d6c853d27fa988169a100ce8 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Thu, 18 May 2023 14:58:05 +0300 Subject: [PATCH 49/52] refactor: added deps to useEffect --- .../components/src/components/amount-input/amount-input.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 6ef636729483..f6c9bd052957 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -44,7 +44,7 @@ const AmountInput = ({ const updated_caret_position = displayNumber(value).length - caret_right_offset; target?.setSelectionRange(updated_caret_position, updated_caret_position); setSelection({ selectionStart: updated_caret_position, selectionEnd: updated_caret_position }); - }, [value]); + }, [value, target, displayNumber]); const onChangeHandler: React.ComponentProps['onChange'] = e => { if (!target) setTarget(e.target); From 75116fa73cfc71221b73e14fa86db7b1cac91f1d Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Fri, 19 May 2023 12:28:55 +0300 Subject: [PATCH 50/52] refactor: ChatGPT's solution to the type thing --- .../components/src/components/amount-input/amount-input.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index f6c9bd052957..2a1d004d19e5 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -91,9 +91,9 @@ const AmountInput = ({ onChange?.(newValue); }; - const inputActionHandler = (e: { - currentTarget: { value: string; selectionStart: number | null; selectionEnd: number | null }; - }) => { + const inputActionHandler: React.ComponentProps['onMouseDown'] & + React.ComponentProps['onMouseUp'] & + React.ComponentProps['onKeyDown'] = e => { if (e.currentTarget.selectionStart !== null && e.currentTarget.selectionEnd !== null) { setCaretRightOffset(e.currentTarget.value.length - e.currentTarget.selectionEnd); setSelection({ From e18183254d97e14f14f405ae724e9c2753eee858 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Fri, 19 May 2023 13:36:43 +0300 Subject: [PATCH 51/52] refactor: newValue -> new_value as @heorhi-deriv suggested --- .../src/components/amount-input/amount-input.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/components/src/components/amount-input/amount-input.tsx b/packages/components/src/components/amount-input/amount-input.tsx index 2a1d004d19e5..bd3431374c29 100644 --- a/packages/components/src/components/amount-input/amount-input.tsx +++ b/packages/components/src/components/amount-input/amount-input.tsx @@ -48,13 +48,13 @@ const AmountInput = ({ const onChangeHandler: React.ComponentProps['onChange'] = e => { if (!target) setTarget(e.target); - let newValue = value; + let new_value = value; if (!is_pasting) { // handle ATM typing: // remove all characters that are not digit / point / comma: const input_value = e.target.value.replace(/[^\d.,]/g, ''); if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) - newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); + new_value = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); } else { // handle pasting: const selection_length = selection.selectionEnd - selection.selectionStart; @@ -74,7 +74,7 @@ const AmountInput = ({ // if the value is a valid non-empty string, handle the two scenarios: if ((value === 0 && caret_right_offset === 0) || selection_length === displayNumber(value).length) { // handle pasting when there's nothing entered before it, or it is overridden (intention: reset value): - newValue = Number( + new_value = Number( pasted_value.substring( 0, pasted_value.includes('.') ? max_digits + 1 : max_digits - decimal_places @@ -82,13 +82,13 @@ const AmountInput = ({ ); } else if (input_value.replace(/[.,]/g, '').replace(/^0+/g, '').length <= max_digits) { // handle pasting when there's something entered before it and there's space for the pasted value (intention: add to value): - newValue = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); + new_value = Number(input_value.replace(/[.,]/g, '')) / Math.pow(10, decimal_places); } } } - setValue(newValue); + setValue(new_value); setIsPasting(false); - onChange?.(newValue); + onChange?.(new_value); }; const inputActionHandler: React.ComponentProps['onMouseDown'] & From e18ce83344432ec0a7a466612ea6fc9e8d6fb218 Mon Sep 17 00:00:00 2001 From: Rostik Kayko Date: Tue, 23 May 2023 11:17:16 +0300 Subject: [PATCH 52/52] refactor: remove the demo component for QA --- .../amount-input-for-testing.tsx | 83 ------------------- .../src/modules/traders-hub/index.tsx | 3 - 2 files changed, 86 deletions(-) delete mode 100644 packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx diff --git a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx b/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx deleted file mode 100644 index 9f0fc6298c3d..000000000000 --- a/packages/appstore/src/components/modals/amount-input-for-testing/amount-input-for-testing.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React, { useState } from 'react'; -import { AmountInput } from '@deriv/components'; - -const AmountInputForTesting = () => { - const [currency, setCurrency] = useState('USD'); - const [disabled, setDisabled] = useState(false); - const [max_digits, setMaxDigits] = useState(8); - const [decimal_points, setDecimalPoints] = useState(2); - - return ( -
-
- Currency: - setCurrency(e.target.value)} /> -
-
- Disabled: - setDisabled(!disabled)} /> -
-
- Max digits: - setMaxDigits(+e.target.value)} - /> -
-
- Decimal points: - setDecimalPoints(+e.target.value)} - /> -
- -
- ); -}; - -export default AmountInputForTesting; diff --git a/packages/appstore/src/modules/traders-hub/index.tsx b/packages/appstore/src/modules/traders-hub/index.tsx index 50d87744017d..bb3689125751 100644 --- a/packages/appstore/src/modules/traders-hub/index.tsx +++ b/packages/appstore/src/modules/traders-hub/index.tsx @@ -14,7 +14,6 @@ import classNames from 'classnames'; import WalletsBanner from 'Components/wallets-banner'; import './traders-hub.scss'; import WalletHeader from 'Components/wallet-header'; -import AmountInputForTesting from '../../components/modals/amount-input-for-testing/amount-input-for-testing'; const TradersHub = () => { const { traders_hub, client, ui } = useStores(); @@ -105,7 +104,6 @@ const TradersHub = () => {
-
@@ -124,7 +122,6 @@ const TradersHub = () => { )} {selected_platform_type === 'options' && } {selected_platform_type === 'cfd' && } - {scrolled && }