This repository was archived by the owner on May 20, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHashHandlingDemo.tsx
More file actions
221 lines (198 loc) · 7.72 KB
/
HashHandlingDemo.tsx
File metadata and controls
221 lines (198 loc) · 7.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import { type ComponentProps, useState } from 'react'
import styled, { css } from 'styled-components'
import {
Textfield as BaseTextfield,
Spinner,
breakpointMediaQuery,
} from '@bootnodedev/db-ui-toolkit'
import type { Address } from 'viem'
import * as chains from 'viem/chains'
import HashDemo from '@/src/components/pageComponents/home/Examples/demos/HashDemo'
import HashInput from '@/src/components/sharedComponents/HashInput'
import { useWeb3Status } from '@/src/hooks/useWeb3Status'
import type { DetectedHash } from '@/src/utils/hash'
const AlertIcon = () => (
<svg
fill="none"
height="21"
viewBox="0 0 22 21"
width="22"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 0C8.9233 0 6.89323 0.615814 5.16652 1.76957C3.4398 2.92332 2.09399 4.5632 1.29927 6.48182C0.504549 8.40045 0.296615 10.5116 0.701759 12.5484C1.1069 14.5852 2.10693 16.4562 3.57538 17.9246C5.04383 19.3931 6.91475 20.3931 8.95155 20.7982C10.9884 21.2034 13.0996 20.9954 15.0182 20.2007C16.9368 19.406 18.5767 18.0602 19.7304 16.3335C20.8842 14.6068 21.5 12.5767 21.5 10.5C21.4971 7.71613 20.3899 5.04712 18.4214 3.07862C16.4529 1.11013 13.7839 0.00293982 11 0ZM11 19.3846C9.24279 19.3846 7.52504 18.8635 6.06398 17.8873C4.60291 16.911 3.46414 15.5234 2.79169 13.9C2.11923 12.2765 1.94329 10.4901 2.2861 8.7667C2.62892 7.04325 3.4751 5.46016 4.71763 4.21763C5.96017 2.97509 7.54325 2.12891 9.2667 1.7861C10.9901 1.44328 12.7765 1.61923 14.4 2.29169C16.0234 2.96414 17.411 4.1029 18.3873 5.56397C19.3635 7.02504 19.8846 8.74279 19.8846 10.5C19.8819 12.8555 18.945 15.1138 17.2794 16.7794C15.6138 18.445 13.3555 19.3819 11 19.3846ZM10.1923 11.3077V5.65384C10.1923 5.43963 10.2774 5.23419 10.4289 5.08272C10.5803 4.93125 10.7858 4.84615 11 4.84615C11.2142 4.84615 11.4197 4.93125 11.5711 5.08272C11.7226 5.23419 11.8077 5.43963 11.8077 5.65384V11.3077C11.8077 11.5219 11.7226 11.7273 11.5711 11.8788C11.4197 12.0303 11.2142 12.1154 11 12.1154C10.7858 12.1154 10.5803 12.0303 10.4289 11.8788C10.2774 11.7273 10.1923 11.5219 10.1923 11.3077ZM12.2115 14.9423C12.2115 15.1819 12.1405 15.4162 12.0074 15.6154C11.8742 15.8146 11.685 15.9699 11.4636 16.0616C11.2423 16.1533 10.9987 16.1773 10.7636 16.1306C10.5286 16.0838 10.3128 15.9684 10.1433 15.799C9.97388 15.6296 9.85849 15.4137 9.81174 15.1787C9.765 14.9436 9.78899 14.7 9.88069 14.4787C9.97239 14.2573 10.1277 14.0681 10.3269 13.9349C10.5261 13.8018 10.7604 13.7308 11 13.7308C11.3213 13.7308 11.6295 13.8584 11.8567 14.0856C12.0839 14.3128 12.2115 14.621 12.2115 14.9423Z"
fill="currentColor"
/>
</svg>
)
const IconOK = ({ ...restProps }) => (
<svg
fill="none"
height="13"
viewBox="0 0 19 13"
width="19"
xmlns="http://www.w3.org/2000/svg"
{...restProps}
>
<path
d="M17.5 1L6.5 12L1.5 7"
stroke="#29BD7F"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
)
const Wrapper = styled.div`
position: relative;
width: 100%;
display: grid;
row-gap: var(--base-gap);
`
const InputWrapper = styled.div`
--base-horizontal-padding: var(--base-common-padding-xl);
--base-textfield-padding: 0 var(--base-horizontal-padding);
--base-textfield-border-radius: var(--base-border-radius);
[data-theme='light'] & {
--theme-textfield-color: #2e3048;
--theme-textfield-color-active: #2e3048;
--theme-textfield-color-error: #2e3048;
--theme-textfield-color-ok: #2e3048;
--theme-textfield-background-color: #f7f7f7;
--theme-textfield-background-color-active: #f7f7f7;
--theme-textfield-border-color: #c5c2cb;
--theme-textfield-border-color-active: #c5c2cb;
--theme-textfield-border-color-error: #2e3048;
--theme-textfield-border-color-ok: #c5c2cb;
--theme-textfield-placeholder-color: rgb(22 29 26 / 60%);
--theme-hash-input-search-status-background-color: #2e3048;
}
[data-theme='dark'] & {
--theme-textfield-color: #fff;
--theme-textfield-color-active: #fff;
--theme-textfield-color-error: #fff;
--theme-textfield-color-ok: #fff;
--theme-textfield-background-color: #2e3048;
--theme-textfield-background-color-active: #2e3048;
--theme-textfield-border-color: #5f6178;
--theme-textfield-border-color-active: #5f6178;
--theme-textfield-border-color-error: #4b4d60;
--theme-textfield-border-color-ok: #5f6178;
--theme-textfield-placeholder-color: rgb(247 247 247 / 60%);
--theme-hash-input-search-status-background-color: #232436;
}
position: relative;
width: 100%;
`
const Textfield = styled(BaseTextfield)<ComponentProps<'input'>>`
display: block;
padding-right: calc(var(--base-common-padding) * 6);
position: relative;
width: 100%;
z-index: 10;
`
const OK = styled(IconOK)`
position: absolute;
right: var(--base-common-padding-xl);
top: 50%;
transform: translateY(-50%);
z-index: 15;
`
const SpinnerWrapper = styled.div`
align-items: center;
display: flex;
height: 100%;
justify-content: center;
position: absolute;
right: 0;
top: 0;
width: calc(var(--base-common-padding) * 6);
z-index: 15;
`
const StatusMessage = styled.div`
align-items: center;
background-color: var(--theme-hash-input-search-status-background-color);
border: 1px solid var(--theme-textfield-border-color-error);
border-radius: var(--base-textfield-border-radius);
color: #fab754;
column-gap: var(--base-gap);
display: flex;
font-size: 1.4rem;
left: 0;
min-height: 64px;
padding: calc(var(--base-common-padding-xl) * 2) var(--base-horizontal-padding)
var(--base-common-padding-xl) var(--base-horizontal-padding);
position: absolute;
top: calc(100% - var(--base-common-padding-xl));
width: 100%;
z-index: 5;
`
const HashExplorer = styled(HashDemo)`
font-size: 1.4rem;
width: 100%;
${breakpointMediaQuery(
'tabletPortraitStart',
css`
position: absolute;
top: calc(100% + var(--base-gap));
`,
)}
`
/**
* This demo shows how to use the HashInput and Hash components.
*
* We use `HashInput` to validate an address or tx hash, and `Hash` to allow the
* user to copy it or open it in an block explorer.
*/
const HashHandlingDemo = ({ ...restProps }) => {
const [searchResult, setSearchResult] = useState<DetectedHash | null>(null)
const [loading, setLoading] = useState<boolean | undefined>()
const notFound = searchResult && searchResult.type === null
const found = searchResult && searchResult.type !== null
const { isWalletConnected, walletChainId } = useWeb3Status()
const onLoading = (isLoading: boolean) => {
setLoading(isLoading)
}
const findChain = (chainId: number) => Object.values(chains).find((chain) => chain.id === chainId)
// mainnet is the default chain if not connected or the chain is not found
const currentChain =
isWalletConnected && walletChainId ? findChain(walletChainId) || chains.mainnet : chains.mainnet
return (
<Wrapper {...restProps}>
<InputWrapper>
<HashInput
chain={currentChain}
onLoading={onLoading}
onSearch={setSearchResult}
renderInput={({ ...props }) => (
<Textfield
$status={notFound ? 'error' : undefined}
placeholder="Address / Tx Hash"
{...props}
/>
)}
/>
{loading && (
<SpinnerWrapper>
<Spinner
height="25"
width="25"
/>
</SpinnerWrapper>
)}
{found && !loading && <OK />}
{notFound && (
<StatusMessage>
<AlertIcon /> <span>No results found</span>
</StatusMessage>
)}
</InputWrapper>
<HashExplorer
chain={currentChain}
hash={searchResult?.data as Address}
truncatedHashLength="disabled"
/>
</Wrapper>
)
}
export default HashHandlingDemo