Skip to content

Commit d3786c8

Browse files
authored
feat: Optimize the input interaction of the CryptoInput component (#1193)
* 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
1 parent 4e1e972 commit d3786c8

File tree

3 files changed

+62
-45
lines changed

3 files changed

+62
-45
lines changed

.changeset/plenty-flowers-live.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@ant-design/web3': patch
3+
---
4+
5+
feat: Optimize the input interaction of the CryptoInput component

packages/web3/src/crypto-input/__tests__/index.test.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,18 @@ describe('CryptoInput component', () => {
8080

8181
it('should call onChange with selected token and amount input', () => {
8282
const TestComponent = (props: CryptoInputProps) => {
83-
const [crypto, setCrypto] = useState<CryptoInputProps['value']>();
83+
const [crypto, setCrypto] = useState<CryptoInputProps['value']>({
84+
inputString: '10',
85+
amount: 0n,
86+
token: undefined,
87+
});
8488

8589
return (
8690
<CryptoInput
8791
options={mockTokens}
8892
value={crypto}
8993
onChange={(newCrypto) => {
9094
setCrypto(newCrypto);
91-
9295
props.onChange?.(newCrypto);
9396
}}
9497
/>
@@ -99,18 +102,24 @@ describe('CryptoInput component', () => {
99102

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

102-
fireEvent.mouseDown(baseElement.querySelector('.ant-select-selector') as Element);
103-
104-
const selectOptions = baseElement.querySelectorAll('.ant-select-item');
105-
106-
fireEvent.click(selectOptions[0]);
105+
fireEvent.change(baseElement.querySelector('.ant-input-number-input') as Element, {
106+
target: { value: '' },
107+
});
107108

108-
expect(handleChange).toHaveBeenCalledWith({ token: mockTokens[0] });
109+
expect(handleChange).toHaveBeenCalledWith({});
109110

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

115+
expect(handleChange).toHaveBeenCalledWith({ inputString: '10' });
116+
117+
fireEvent.mouseDown(baseElement.querySelector('.ant-select-selector') as Element);
118+
119+
const selectOptions = baseElement.querySelectorAll('.ant-select-item');
120+
121+
fireEvent.click(selectOptions[0]);
122+
114123
expect(handleChange).toHaveBeenCalledWith({
115124
token: mockTokens[0],
116125
amount: 10000000000000000000n,

packages/web3/src/crypto-input/index.tsx

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,44 @@ export const CryptoInput: React.FC<CryptoInputProps> = ({
7070
: undefined,
7171
);
7272

73+
// 将 InputNumber 的 onChange 和 TokenSelect 的 onChange 合并
74+
const handleChange = (amt: string | null, curToken?: Token) => {
75+
if (!amt && !curToken) {
76+
onChange?.({});
77+
return;
78+
} else if (!curToken) {
79+
onChange?.({ inputString: amt! });
80+
return;
81+
} else if (!amt) {
82+
onChange?.({ token: curToken });
83+
return;
84+
}
85+
86+
const [integers, decimals] = String(amt).split('.');
87+
88+
let inputAmt = amt;
89+
90+
// if precision is more than token decimal, cut it
91+
if (decimals?.length > curToken.decimal) {
92+
inputAmt = `${integers}.${decimals.slice(0, curToken.decimal)}`;
93+
}
94+
95+
// covert string amt to bigint
96+
97+
const newAmt = BigInt(
98+
new Decimal100(inputAmt)
99+
.times(Decimal100.pow(10, curToken.decimal))
100+
.toFixed(0, Decimal100.ROUND_DOWN),
101+
);
102+
103+
onChange?.({
104+
...value,
105+
amount: newAmt,
106+
inputString: inputAmt,
107+
token: curToken,
108+
});
109+
};
110+
73111
return wrapSSR(
74112
<Flex vertical className={getClsName('wrapper')}>
75113
{header && <div className={getClsName('header')}>{header}</div>}
@@ -82,48 +120,13 @@ export const CryptoInput: React.FC<CryptoInputProps> = ({
82120
placeholder={messages.placeholder}
83121
value={inputString}
84122
// remove unnecessary 0 at the end of the number
85-
onChange={(amt) => {
86-
// if amount is null or token is not selected, clean the value
87-
if (isNull(amt) || !token) {
88-
onChange?.({
89-
token,
90-
});
91-
return;
92-
}
93-
94-
const [integers, decimals] = String(amt).split('.');
95-
96-
let inputAmt = amt;
97-
98-
// if precision is more than token decimal, cut it
99-
if (decimals?.length > token.decimal) {
100-
inputAmt = `${integers}.${decimals.slice(0, token.decimal)}`;
101-
}
102-
103-
// covert string amt to bigint
104-
105-
const newAmt = BigInt(
106-
new Decimal100(inputAmt)
107-
.times(Decimal100.pow(10, token.decimal))
108-
.toFixed(0, Decimal100.ROUND_DOWN),
109-
);
110-
111-
onChange?.({
112-
...value,
113-
amount: newAmt,
114-
inputString: inputAmt,
115-
});
116-
}}
123+
onChange={(amt) => handleChange(amt, token)}
117124
addonAfter={
118125
<TokenSelect
119126
variant="borderless"
120127
{...selectProps}
121128
value={value?.token}
122-
onChange={(newToken) =>
123-
onChange?.({
124-
token: newToken,
125-
})
126-
}
129+
onChange={(newToken) => handleChange(inputString || '', newToken)}
127130
size={size}
128131
/>
129132
}

0 commit comments

Comments
 (0)