Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 90531e3

Browse files
authored
Added AddressInput Component (#167)
* added AddressInput component * Fixed TextField styles * Added new TextFieldInput and deprecated TextField Component * Added deterministic classnames when you run snapshot tests * Added Fixed Number Format in tests
1 parent 04fb1a4 commit 90531e3

File tree

35 files changed

+2768
-364
lines changed

35 files changed

+2768
-364
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"author": "Gnosis (https://gnosis.pm)",
2626
"license": "MIT",
2727
"dependencies": {
28+
"web3-utils": "^1.6.0",
2829
"react-media": "^1.10.0"
2930
},
3031
"devDependencies": {
@@ -33,6 +34,7 @@
3334
"@babel/preset-react": "^7.16.0",
3435
"@babel/preset-typescript": "^7.16.0",
3536
"@material-ui/core": "^4.12.3",
37+
"@material-ui/icons": "^4.11.0",
3638
"@storybook/addon-actions": "^6.3.12",
3739
"@storybook/addon-docs": "^6.3.12",
3840
"@storybook/addon-links": "^6.3.12",
Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { InputAdornment } from '@material-ui/core';
3+
import styled from 'styled-components';
4+
import CheckCircle from '@material-ui/icons/CheckCircle';
5+
import { Typography } from '@material-ui/core';
6+
7+
import AddressInput from './index';
8+
import { isValidAddress } from '../../utils/address';
9+
import { Switch } from '..';
10+
11+
export default {
12+
title: 'Inputs/AddressInput',
13+
component: AddressInput,
14+
parameters: {
15+
componentSubtitle: 'Address field input with several variants',
16+
},
17+
};
18+
19+
const onSubmit = (e: React.FormEvent) => e.preventDefault();
20+
21+
export const SimpleAddressInput = (): React.ReactElement => {
22+
const [address, setAddress] = useState<string>(
23+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
24+
);
25+
const [showNetworkPrefix, setShowNetworkPrefix] = useState<boolean>(true);
26+
27+
const getAddressFromDomain = () =>
28+
new Promise<string>((resolve) => {
29+
setTimeout(
30+
() => resolve('0x83eC7B0506556a7749306D69681aDbDbd08f0769'),
31+
1200
32+
);
33+
});
34+
35+
return (
36+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
37+
<Typography style={{ marginBottom: '16px' }}>
38+
<Switch checked={showNetworkPrefix} onChange={setShowNetworkPrefix} />
39+
Show Network Prefix (rin)
40+
</Typography>
41+
<AddressInput
42+
id={'address-input'}
43+
label="Ethereum Address"
44+
name="address"
45+
placeholder={'Ethereum address'}
46+
showNetworkPrefix={showNetworkPrefix}
47+
networkPrefix={'rin'}
48+
address={address}
49+
onChangeAddress={(address) => setAddress(address)}
50+
getAddressFromDomain={getAddressFromDomain}
51+
/>
52+
<Typography style={{ marginTop: '24px' }}>
53+
Address value in the State:{' '}
54+
</Typography>
55+
<pre
56+
style={{
57+
display: 'inline-block',
58+
backgroundColor: 'lightgrey',
59+
marginLeft: '8px',
60+
margin: '0',
61+
padding: '8px',
62+
minWidth: '500px',
63+
borderRadius: '4px',
64+
}}>
65+
{address || ' '}
66+
</pre>
67+
<Typography style={{ marginTop: '16px' }}>
68+
You can use ENS names (like safe.test) with the getAddressFromDomain
69+
prop
70+
</Typography>
71+
</form>
72+
);
73+
};
74+
75+
export const AddressInputWithNetworkPrefix = (): React.ReactElement => {
76+
const [address, setAddress] = useState<string>(
77+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
78+
);
79+
80+
return (
81+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
82+
<AddressInput
83+
label="Prefixed Address"
84+
name="prefixed-address"
85+
networkPrefix="rin"
86+
placeholder={'Ethereum address'}
87+
showNetworkPrefix={true}
88+
address={address}
89+
onChangeAddress={(address) => setAddress(address)}
90+
/>
91+
<pre>Address in the state: {address}</pre>
92+
</form>
93+
);
94+
};
95+
96+
export const AddressInputWithValidation = (): React.ReactElement => {
97+
const [address, setAddress] = useState<string>(
98+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
99+
);
100+
const [hasError, setHasError] = useState<boolean>(
101+
() => !isValidAddress(address)
102+
);
103+
104+
useEffect(() => {
105+
setHasError(!isValidAddress(address));
106+
}, [address]);
107+
108+
const error = 'Invalid Address';
109+
110+
return (
111+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
112+
<AddressInput
113+
label="Address"
114+
name="address"
115+
placeholder={'Ethereum address'}
116+
networkPrefix="rin"
117+
showNetworkPrefix={false}
118+
error={hasError ? error : ''}
119+
address={address}
120+
onChangeAddress={(address) => setAddress(address)}
121+
/>
122+
</form>
123+
);
124+
};
125+
126+
export const AddressInputWithoutPrefix = (): React.ReactElement => {
127+
const [address, setAddress] = useState<string>(
128+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
129+
);
130+
131+
return (
132+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
133+
<AddressInput
134+
label="Address"
135+
name="address"
136+
placeholder={'Ethereum address'}
137+
networkPrefix="rin"
138+
showNetworkPrefix={false}
139+
address={address}
140+
onChangeAddress={(address) => setAddress(address)}
141+
/>
142+
</form>
143+
);
144+
};
145+
146+
export const AddressInputWithENSResolution = (): React.ReactElement => {
147+
const [address, setAddress] = useState<string>(
148+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
149+
);
150+
151+
const getAddressFromDomain = () =>
152+
new Promise<string>((resolve) => {
153+
setTimeout(
154+
() => resolve('0x83eC7B0506556a7749306D69681aDbDbd08f0769'),
155+
2000
156+
);
157+
});
158+
159+
return (
160+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
161+
<AddressInput
162+
label="Address"
163+
name="address"
164+
placeholder={'Ethereum address'}
165+
networkPrefix="rin"
166+
showNetworkPrefix={true}
167+
address={address}
168+
onChangeAddress={(address) => setAddress(address)}
169+
getAddressFromDomain={getAddressFromDomain}
170+
/>
171+
</form>
172+
);
173+
};
174+
175+
export const SafeAddressInputValidation = (): React.ReactElement => {
176+
const [address, setAddress] = useState<string>(
177+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
178+
);
179+
const [isValidSafeAddress, setIsValidSafeAddress] = useState<boolean>(false);
180+
const [showLoadingSpinner, setShowLoadingSpinner] = useState<boolean>(false);
181+
182+
// check if address is the SafeAddress
183+
useEffect(() => {
184+
setShowLoadingSpinner(true);
185+
setIsValidSafeAddress(false);
186+
187+
const timeId = setTimeout(() => {
188+
const isValidSafeAddress =
189+
address === '0x83eC7B0506556a7749306D69681aDbDbd08f0769';
190+
setIsValidSafeAddress(isValidSafeAddress);
191+
setShowLoadingSpinner(false);
192+
}, 1200);
193+
194+
return () => {
195+
clearTimeout(timeId);
196+
};
197+
}, [address]);
198+
199+
const error = 'Address given is not a valid Safe address';
200+
201+
const showError = !isValidSafeAddress && !showLoadingSpinner;
202+
203+
return (
204+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
205+
<AddressInput
206+
label="Safe Address"
207+
name="safeAddress"
208+
networkPrefix="rin"
209+
placeholder={'Ethereum address'}
210+
showNetworkPrefix={false}
211+
error={showError ? error : ''}
212+
address={address}
213+
onChangeAddress={(address) => setAddress(address)}
214+
showLoadingSpinner={showLoadingSpinner}
215+
InputProps={{
216+
endAdornment: isValidSafeAddress && (
217+
<InputAdornment position="end">
218+
<CheckIconAddressAdornment />
219+
</InputAdornment>
220+
),
221+
}}
222+
/>
223+
</form>
224+
);
225+
};
226+
227+
export const AddressInputLoading = (): React.ReactElement => {
228+
const [address, setAddress] = useState<string>(
229+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
230+
);
231+
232+
return (
233+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
234+
<AddressInput
235+
label="Address"
236+
name="address"
237+
networkPrefix="rin"
238+
showNetworkPrefix={false}
239+
placeholder={'Ethereum address'}
240+
showLoadingSpinner
241+
address={address}
242+
onChangeAddress={(address) => setAddress(address)}
243+
/>
244+
</form>
245+
);
246+
};
247+
248+
export const AddressInputWithAdornment = (): React.ReactElement => {
249+
const [address, setAddress] = useState<string>(
250+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
251+
);
252+
253+
return (
254+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
255+
<AddressInput
256+
label="Address"
257+
name="address"
258+
networkPrefix="rin"
259+
showNetworkPrefix={false}
260+
showLoadingSpinner={false}
261+
placeholder={'Ethereum address'}
262+
InputProps={{
263+
endAdornment: (
264+
<InputAdornment position="end">
265+
<CheckIconAddressAdornment />
266+
</InputAdornment>
267+
),
268+
}}
269+
address={address}
270+
onChangeAddress={(address) => setAddress(address)}
271+
/>
272+
</form>
273+
);
274+
};
275+
276+
export const AddressInputDisabled = (): React.ReactElement => {
277+
const [address, setAddress] = useState<string>(
278+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
279+
);
280+
281+
return (
282+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
283+
<AddressInput
284+
label="Address"
285+
name="address"
286+
networkPrefix="rin"
287+
showNetworkPrefix={false}
288+
showLoadingSpinner={false}
289+
disabled
290+
placeholder={'Ethereum address'}
291+
address={address}
292+
onChangeAddress={(address) => setAddress(address)}
293+
/>
294+
</form>
295+
);
296+
};
297+
298+
export const AddressInputWithErrors = (): React.ReactElement => {
299+
const [address, setAddress] = useState<string>(
300+
'0x83eC7B0506556a7749306D69681aDbDbd08f0769'
301+
);
302+
303+
return (
304+
<form noValidate autoComplete="off" onSubmit={onSubmit}>
305+
<AddressInput
306+
label="Address"
307+
name="address"
308+
networkPrefix="rin"
309+
showNetworkPrefix={false}
310+
placeholder={'Ethereum address'}
311+
showLoadingSpinner={false}
312+
address={address}
313+
onChangeAddress={(address) => setAddress(address)}
314+
error={'Invalid Address'}
315+
/>
316+
</form>
317+
);
318+
};
319+
320+
const CheckIconAddressAdornment = styled(CheckCircle)`
321+
color: #03ae60;
322+
height: 20px;
323+
`;

0 commit comments

Comments
 (0)