Skip to content

Commit

Permalink
feat: Optimize the input interaction of the CryptoInput component (#1193
Browse files Browse the repository at this point in the history
)

* feat: Optimize the input interaction of the CryptoInput component

* chore: update changeset

* test: update test case

* test: update test case

* test: update test case

* Update packages/web3/src/crypto-input/__tests__/index.test.tsx
  • Loading branch information
kiner-tang authored Oct 8, 2024
1 parent 4e1e972 commit d3786c8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 45 deletions.
5 changes: 5 additions & 0 deletions .changeset/plenty-flowers-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ant-design/web3': patch
---

feat: Optimize the input interaction of the CryptoInput component
25 changes: 17 additions & 8 deletions packages/web3/src/crypto-input/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,18 @@ describe('CryptoInput component', () => {

it('should call onChange with selected token and amount input', () => {
const TestComponent = (props: CryptoInputProps) => {
const [crypto, setCrypto] = useState<CryptoInputProps['value']>();
const [crypto, setCrypto] = useState<CryptoInputProps['value']>({
inputString: '10',
amount: 0n,
token: undefined,
});

return (
<CryptoInput
options={mockTokens}
value={crypto}
onChange={(newCrypto) => {
setCrypto(newCrypto);

props.onChange?.(newCrypto);
}}
/>
Expand All @@ -99,18 +102,24 @@ describe('CryptoInput component', () => {

const { baseElement } = render(<TestComponent onChange={handleChange} />);

fireEvent.mouseDown(baseElement.querySelector('.ant-select-selector') as Element);

const selectOptions = baseElement.querySelectorAll('.ant-select-item');

fireEvent.click(selectOptions[0]);
fireEvent.change(baseElement.querySelector('.ant-input-number-input') as Element, {
target: { value: '' },
});

expect(handleChange).toHaveBeenCalledWith({ token: mockTokens[0] });
expect(handleChange).toHaveBeenCalledWith({});

fireEvent.change(baseElement.querySelector('.ant-input-number-input') as Element, {
target: { value: '10' },
});

expect(handleChange).toHaveBeenCalledWith({ inputString: '10' });

fireEvent.mouseDown(baseElement.querySelector('.ant-select-selector') as Element);

const selectOptions = baseElement.querySelectorAll('.ant-select-item');

fireEvent.click(selectOptions[0]);

expect(handleChange).toHaveBeenCalledWith({
token: mockTokens[0],
amount: 10000000000000000000n,
Expand Down
77 changes: 40 additions & 37 deletions packages/web3/src/crypto-input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,44 @@ export const CryptoInput: React.FC<CryptoInputProps> = ({
: undefined,
);

// 将 InputNumber 的 onChange 和 TokenSelect 的 onChange 合并
const handleChange = (amt: string | null, curToken?: Token) => {
if (!amt && !curToken) {
onChange?.({});
return;
} else if (!curToken) {
onChange?.({ inputString: amt! });
return;
} else if (!amt) {
onChange?.({ token: curToken });
return;
}

const [integers, decimals] = String(amt).split('.');

let inputAmt = amt;

// if precision is more than token decimal, cut it
if (decimals?.length > curToken.decimal) {
inputAmt = `${integers}.${decimals.slice(0, curToken.decimal)}`;
}

// covert string amt to bigint

const newAmt = BigInt(
new Decimal100(inputAmt)
.times(Decimal100.pow(10, curToken.decimal))
.toFixed(0, Decimal100.ROUND_DOWN),
);

onChange?.({
...value,
amount: newAmt,
inputString: inputAmt,
token: curToken,
});
};

return wrapSSR(
<Flex vertical className={getClsName('wrapper')}>
{header && <div className={getClsName('header')}>{header}</div>}
Expand All @@ -82,48 +120,13 @@ export const CryptoInput: React.FC<CryptoInputProps> = ({
placeholder={messages.placeholder}
value={inputString}
// remove unnecessary 0 at the end of the number
onChange={(amt) => {
// if amount is null or token is not selected, clean the value
if (isNull(amt) || !token) {
onChange?.({
token,
});
return;
}

const [integers, decimals] = String(amt).split('.');

let inputAmt = amt;

// if precision is more than token decimal, cut it
if (decimals?.length > token.decimal) {
inputAmt = `${integers}.${decimals.slice(0, token.decimal)}`;
}

// covert string amt to bigint

const newAmt = BigInt(
new Decimal100(inputAmt)
.times(Decimal100.pow(10, token.decimal))
.toFixed(0, Decimal100.ROUND_DOWN),
);

onChange?.({
...value,
amount: newAmt,
inputString: inputAmt,
});
}}
onChange={(amt) => handleChange(amt, token)}
addonAfter={
<TokenSelect
variant="borderless"
{...selectProps}
value={value?.token}
onChange={(newToken) =>
onChange?.({
token: newToken,
})
}
onChange={(newToken) => handleChange(inputString || '', newToken)}
size={size}
/>
}
Expand Down

0 comments on commit d3786c8

Please sign in to comment.