@hfunlabs/hypurr-connect 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/index.d.ts +131 -10
- package/dist/index.js +2590 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/DeleteWalletModal.tsx +344 -0
- package/src/HypurrConnectProvider.tsx +31 -18
- package/src/LoginModal.tsx +19 -8
- package/src/RenameWalletModal.tsx +325 -0
- package/src/UserProfileModal.tsx +982 -0
- package/src/WalletSelectorDropdown.tsx +797 -0
- package/src/icons/lucide.tsx +197 -0
- package/src/index.ts +9 -0
- package/src/profileStyles.ts +213 -0
- package/src/types.ts +4 -10
- package/src/TelegramLoginWidget.tsx +0 -62
package/package.json
CHANGED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { AnimatePresence, motion } from "framer-motion";
|
|
2
|
+
import type { HyperliquidWallet } from "hypurr-grpc/ts/hypurr/wallet";
|
|
3
|
+
import {
|
|
4
|
+
useCallback,
|
|
5
|
+
useState,
|
|
6
|
+
type CSSProperties,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
} from "react";
|
|
9
|
+
import {
|
|
10
|
+
AlertTriangle,
|
|
11
|
+
Loader2,
|
|
12
|
+
SpinKeyframes,
|
|
13
|
+
Trash2,
|
|
14
|
+
X,
|
|
15
|
+
} from "./icons/lucide";
|
|
16
|
+
import {
|
|
17
|
+
closeBtnStyle as makeCloseBtnStyle,
|
|
18
|
+
dangerOutlineButtonStyle,
|
|
19
|
+
fontFamily,
|
|
20
|
+
modalBackdropStyle,
|
|
21
|
+
modalHeaderStyle,
|
|
22
|
+
modalPanelStyle,
|
|
23
|
+
modalWrapperStyle,
|
|
24
|
+
profileColors,
|
|
25
|
+
titleStyle,
|
|
26
|
+
upperLabelStyle,
|
|
27
|
+
} from "./profileStyles";
|
|
28
|
+
|
|
29
|
+
export interface DeleteWalletModalProps {
|
|
30
|
+
isOpen: boolean;
|
|
31
|
+
onClose: () => void;
|
|
32
|
+
wallet: HyperliquidWallet | null;
|
|
33
|
+
onConfirm: (walletId: number) => Promise<void>;
|
|
34
|
+
/** Optional toast callback. Fires `{type:"success"}` on delete; errors are shown inline. */
|
|
35
|
+
onNotify?: (n: { type: "success" | "error"; message: string }) => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const DANGER_BG = "rgba(248,113,113,0.07)";
|
|
39
|
+
const DANGER_BORDER = "rgba(248,113,113,0.2)";
|
|
40
|
+
|
|
41
|
+
const backdropStyle = modalBackdropStyle(110);
|
|
42
|
+
const wrapperStyle = modalWrapperStyle(111, 16);
|
|
43
|
+
const panelStyle: CSSProperties = {
|
|
44
|
+
...modalPanelStyle(true),
|
|
45
|
+
border: `1px solid ${profileColors.surfaceBd}`,
|
|
46
|
+
};
|
|
47
|
+
const headerStyle: CSSProperties = {
|
|
48
|
+
...modalHeaderStyle,
|
|
49
|
+
borderBottom: "1px solid rgba(255,255,255,0.06)",
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const bodyStyle: CSSProperties = {
|
|
53
|
+
padding: "20px 24px",
|
|
54
|
+
display: "flex",
|
|
55
|
+
flexDirection: "column",
|
|
56
|
+
gap: 16,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const warningBoxStyle: CSSProperties = {
|
|
60
|
+
display: "flex",
|
|
61
|
+
alignItems: "flex-start",
|
|
62
|
+
gap: 12,
|
|
63
|
+
padding: 14,
|
|
64
|
+
background: DANGER_BG,
|
|
65
|
+
border: `1px solid ${DANGER_BORDER}`,
|
|
66
|
+
borderRadius: 8,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const infoBoxStyle: CSSProperties = {
|
|
70
|
+
padding: "10px 12px",
|
|
71
|
+
background: "rgba(255,255,255,0.03)",
|
|
72
|
+
border: "1px solid rgba(255,255,255,0.06)",
|
|
73
|
+
borderRadius: 8,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const labelStyle: CSSProperties = {
|
|
77
|
+
display: "block",
|
|
78
|
+
fontSize: 12.5,
|
|
79
|
+
lineHeight: "1rem",
|
|
80
|
+
color: profileColors.muted,
|
|
81
|
+
marginBottom: 8,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const inputStyle = (disabled: boolean): CSSProperties => ({
|
|
85
|
+
width: "100%",
|
|
86
|
+
background: "rgba(13,18,25,0.9)",
|
|
87
|
+
border: `1px solid ${profileColors.surfaceBd}`,
|
|
88
|
+
borderRadius: 8,
|
|
89
|
+
padding: "10px 12px",
|
|
90
|
+
color: profileColors.text,
|
|
91
|
+
fontFamily: fontFamily.mono,
|
|
92
|
+
fontSize: 12.5,
|
|
93
|
+
lineHeight: "1rem",
|
|
94
|
+
outline: "none",
|
|
95
|
+
opacity: disabled ? 0.5 : 1,
|
|
96
|
+
boxSizing: "border-box",
|
|
97
|
+
transition: "border-color 150ms, background-color 150ms",
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const footerStyle: CSSProperties = {
|
|
101
|
+
padding: "0 24px 24px",
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const deleteButtonStyle = (
|
|
105
|
+
enabled: boolean,
|
|
106
|
+
hovered: boolean,
|
|
107
|
+
): CSSProperties => ({
|
|
108
|
+
...dangerOutlineButtonStyle(enabled, hovered),
|
|
109
|
+
width: "100%",
|
|
110
|
+
padding: "8px 0",
|
|
111
|
+
borderRadius: 8,
|
|
112
|
+
fontSize: 12.5,
|
|
113
|
+
lineHeight: "1rem",
|
|
114
|
+
fontWeight: 500,
|
|
115
|
+
display: "flex",
|
|
116
|
+
alignItems: "center",
|
|
117
|
+
justifyContent: "center",
|
|
118
|
+
gap: 8,
|
|
119
|
+
transition: "background-color 150ms, color 150ms, border-color 150ms",
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export function DeleteWalletModal({
|
|
123
|
+
isOpen,
|
|
124
|
+
onClose,
|
|
125
|
+
wallet,
|
|
126
|
+
onConfirm,
|
|
127
|
+
onNotify,
|
|
128
|
+
}: DeleteWalletModalProps): ReactNode {
|
|
129
|
+
const [confirmName, setConfirmName] = useState("");
|
|
130
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
131
|
+
const [error, setError] = useState<string | null>(null);
|
|
132
|
+
const [deleteHovered, setDeleteHovered] = useState(false);
|
|
133
|
+
|
|
134
|
+
const walletName = wallet?.name || "Unnamed Wallet";
|
|
135
|
+
const isNameMatch = confirmName === walletName;
|
|
136
|
+
const canDelete = isNameMatch && !isDeleting;
|
|
137
|
+
|
|
138
|
+
const handleClose = useCallback(() => {
|
|
139
|
+
if (isDeleting) return;
|
|
140
|
+
setConfirmName("");
|
|
141
|
+
setError(null);
|
|
142
|
+
onClose();
|
|
143
|
+
}, [isDeleting, onClose]);
|
|
144
|
+
|
|
145
|
+
const handleDelete = useCallback(async () => {
|
|
146
|
+
if (!wallet || !isNameMatch) return;
|
|
147
|
+
setError(null);
|
|
148
|
+
setIsDeleting(true);
|
|
149
|
+
try {
|
|
150
|
+
await onConfirm(wallet.id);
|
|
151
|
+
setConfirmName("");
|
|
152
|
+
onNotify?.({ type: "success", message: "Wallet deleted successfully" });
|
|
153
|
+
onClose();
|
|
154
|
+
} catch (e: unknown) {
|
|
155
|
+
setError(e instanceof Error ? e.message : "Failed to delete wallet");
|
|
156
|
+
} finally {
|
|
157
|
+
setIsDeleting(false);
|
|
158
|
+
}
|
|
159
|
+
}, [wallet, isNameMatch, onConfirm, onClose, onNotify]);
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<AnimatePresence>
|
|
163
|
+
{isOpen && wallet && (
|
|
164
|
+
<>
|
|
165
|
+
<SpinKeyframes />
|
|
166
|
+
<motion.div
|
|
167
|
+
key="backdrop"
|
|
168
|
+
style={backdropStyle}
|
|
169
|
+
initial={{ opacity: 0 }}
|
|
170
|
+
animate={{ opacity: 1 }}
|
|
171
|
+
exit={{ opacity: 0 }}
|
|
172
|
+
transition={{ duration: 0.15 }}
|
|
173
|
+
onClick={handleClose}
|
|
174
|
+
/>
|
|
175
|
+
<div style={wrapperStyle}>
|
|
176
|
+
<motion.div
|
|
177
|
+
key="panel"
|
|
178
|
+
style={panelStyle}
|
|
179
|
+
initial={{ opacity: 0, y: 8 }}
|
|
180
|
+
animate={{ opacity: 1, y: 0 }}
|
|
181
|
+
exit={{ opacity: 0, y: 8 }}
|
|
182
|
+
transition={{ duration: 0.18, ease: "easeOut" }}
|
|
183
|
+
onClick={(e) => e.stopPropagation()}
|
|
184
|
+
>
|
|
185
|
+
<div style={headerStyle}>
|
|
186
|
+
<h3 style={titleStyle}>Delete Wallet</h3>
|
|
187
|
+
<button
|
|
188
|
+
onClick={handleClose}
|
|
189
|
+
disabled={isDeleting}
|
|
190
|
+
style={makeCloseBtnStyle(isDeleting)}
|
|
191
|
+
aria-label="Close"
|
|
192
|
+
>
|
|
193
|
+
<X size={16} />
|
|
194
|
+
</button>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<div style={bodyStyle}>
|
|
198
|
+
<div style={warningBoxStyle}>
|
|
199
|
+
<AlertTriangle
|
|
200
|
+
size={15}
|
|
201
|
+
color={profileColors.danger}
|
|
202
|
+
style={{ flexShrink: 0, marginTop: 2 }}
|
|
203
|
+
/>
|
|
204
|
+
<div>
|
|
205
|
+
<p
|
|
206
|
+
style={{
|
|
207
|
+
margin: 0,
|
|
208
|
+
fontSize: 12.5,
|
|
209
|
+
lineHeight: "1rem",
|
|
210
|
+
color: profileColors.danger,
|
|
211
|
+
fontWeight: 500,
|
|
212
|
+
}}
|
|
213
|
+
>
|
|
214
|
+
This action cannot be undone
|
|
215
|
+
</p>
|
|
216
|
+
<p
|
|
217
|
+
style={{
|
|
218
|
+
margin: "2px 0 0",
|
|
219
|
+
fontSize: 12.5,
|
|
220
|
+
lineHeight: "1rem",
|
|
221
|
+
color: "rgba(248,113,113,0.7)",
|
|
222
|
+
}}
|
|
223
|
+
>
|
|
224
|
+
The private key will be permanently deleted. Any remaining
|
|
225
|
+
funds will be inaccessible.
|
|
226
|
+
</p>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
<div style={infoBoxStyle}>
|
|
231
|
+
<p
|
|
232
|
+
style={{
|
|
233
|
+
margin: "0 0 4px",
|
|
234
|
+
color: profileColors.muted,
|
|
235
|
+
...upperLabelStyle,
|
|
236
|
+
}}
|
|
237
|
+
>
|
|
238
|
+
Wallet to delete
|
|
239
|
+
</p>
|
|
240
|
+
<p
|
|
241
|
+
style={{
|
|
242
|
+
margin: 0,
|
|
243
|
+
fontSize: 12.5,
|
|
244
|
+
lineHeight: "1rem",
|
|
245
|
+
fontWeight: 500,
|
|
246
|
+
color: profileColors.text,
|
|
247
|
+
}}
|
|
248
|
+
>
|
|
249
|
+
{walletName}
|
|
250
|
+
</p>
|
|
251
|
+
<p
|
|
252
|
+
style={{
|
|
253
|
+
margin: "2px 0 0",
|
|
254
|
+
fontSize: 12.5,
|
|
255
|
+
lineHeight: "1rem",
|
|
256
|
+
color: profileColors.muted,
|
|
257
|
+
fontFamily: fontFamily.mono,
|
|
258
|
+
wordBreak: "break-all",
|
|
259
|
+
}}
|
|
260
|
+
>
|
|
261
|
+
{wallet.ethereumAddress}
|
|
262
|
+
</p>
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<div>
|
|
266
|
+
<label style={labelStyle}>
|
|
267
|
+
Type{" "}
|
|
268
|
+
<span
|
|
269
|
+
style={{
|
|
270
|
+
color: profileColors.text,
|
|
271
|
+
fontWeight: 500,
|
|
272
|
+
}}
|
|
273
|
+
>
|
|
274
|
+
"{walletName}"
|
|
275
|
+
</span>{" "}
|
|
276
|
+
to confirm
|
|
277
|
+
</label>
|
|
278
|
+
<input
|
|
279
|
+
type="text"
|
|
280
|
+
value={confirmName}
|
|
281
|
+
onChange={(e) => setConfirmName(e.target.value)}
|
|
282
|
+
placeholder={walletName}
|
|
283
|
+
disabled={isDeleting}
|
|
284
|
+
style={inputStyle(isDeleting)}
|
|
285
|
+
/>
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
{error && (
|
|
289
|
+
<div
|
|
290
|
+
style={{
|
|
291
|
+
display: "flex",
|
|
292
|
+
alignItems: "flex-start",
|
|
293
|
+
gap: 8,
|
|
294
|
+
padding: 12,
|
|
295
|
+
background: "rgba(248,113,113,0.08)",
|
|
296
|
+
border: `1px solid ${DANGER_BORDER}`,
|
|
297
|
+
borderRadius: 8,
|
|
298
|
+
}}
|
|
299
|
+
>
|
|
300
|
+
<AlertTriangle
|
|
301
|
+
size={14}
|
|
302
|
+
color={profileColors.danger}
|
|
303
|
+
style={{ flexShrink: 0, marginTop: 2 }}
|
|
304
|
+
/>
|
|
305
|
+
<p
|
|
306
|
+
style={{
|
|
307
|
+
margin: 0,
|
|
308
|
+
fontSize: 12.5,
|
|
309
|
+
lineHeight: "1rem",
|
|
310
|
+
color: profileColors.danger,
|
|
311
|
+
}}
|
|
312
|
+
>
|
|
313
|
+
{error}
|
|
314
|
+
</p>
|
|
315
|
+
</div>
|
|
316
|
+
)}
|
|
317
|
+
</div>
|
|
318
|
+
|
|
319
|
+
<div style={footerStyle}>
|
|
320
|
+
<button
|
|
321
|
+
onClick={handleDelete}
|
|
322
|
+
disabled={!canDelete}
|
|
323
|
+
onMouseEnter={() => setDeleteHovered(true)}
|
|
324
|
+
onMouseLeave={() => setDeleteHovered(false)}
|
|
325
|
+
style={deleteButtonStyle(canDelete, deleteHovered)}
|
|
326
|
+
>
|
|
327
|
+
{isDeleting ? (
|
|
328
|
+
<>
|
|
329
|
+
<Loader2 size={14} /> Deleting...
|
|
330
|
+
</>
|
|
331
|
+
) : (
|
|
332
|
+
<>
|
|
333
|
+
<Trash2 size={14} /> Delete Wallet
|
|
334
|
+
</>
|
|
335
|
+
)}
|
|
336
|
+
</button>
|
|
337
|
+
</div>
|
|
338
|
+
</motion.div>
|
|
339
|
+
</div>
|
|
340
|
+
</>
|
|
341
|
+
)}
|
|
342
|
+
</AnimatePresence>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
@@ -52,8 +52,6 @@ import type {
|
|
|
52
52
|
/** @internal context value — extends the public type with fields used only by library internals */
|
|
53
53
|
interface InternalConnectState extends HypurrConnectState {
|
|
54
54
|
loginTelegram: () => void;
|
|
55
|
-
botUsername: string;
|
|
56
|
-
useWidget: boolean;
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
const TELEGRAM_STORAGE_KEY = "hypurr-connect-tg-jwt";
|
|
@@ -504,9 +502,12 @@ export function HypurrConnectProvider({
|
|
|
504
502
|
displayName: tgUser.telegramUsername
|
|
505
503
|
? `@${tgUser.telegramUsername}`
|
|
506
504
|
: `Telegram ${tgUser.telegramId}`,
|
|
507
|
-
photoUrl:
|
|
508
|
-
|
|
509
|
-
|
|
505
|
+
photoUrl: (() => {
|
|
506
|
+
// `pictureFileId` is read at runtime; the schema may not type it.
|
|
507
|
+
const fileId = (tgUser as unknown as { pictureFileId?: string })
|
|
508
|
+
.pictureFileId;
|
|
509
|
+
return fileId ? `${mediaUrl}/${fileId}` : undefined;
|
|
510
|
+
})(),
|
|
510
511
|
authMethod: "telegram",
|
|
511
512
|
telegramId: String(tgUser.telegramId),
|
|
512
513
|
hfunScore: tgUser?.reputation?.hfunScore,
|
|
@@ -912,6 +913,21 @@ export function HypurrConnectProvider({
|
|
|
912
913
|
[tgClient, telegramRpcOptions, selectedWalletId, wallets, refreshWallets],
|
|
913
914
|
);
|
|
914
915
|
|
|
916
|
+
const renameWallet = useCallback(
|
|
917
|
+
async (walletId: number, name: string): Promise<void> => {
|
|
918
|
+
await tgClient.hyperliquidWalletUpdate(
|
|
919
|
+
{
|
|
920
|
+
authData: {},
|
|
921
|
+
walletId,
|
|
922
|
+
name,
|
|
923
|
+
},
|
|
924
|
+
telegramRpcOptions,
|
|
925
|
+
);
|
|
926
|
+
refreshWallets();
|
|
927
|
+
},
|
|
928
|
+
[tgClient, telegramRpcOptions, refreshWallets],
|
|
929
|
+
);
|
|
930
|
+
|
|
915
931
|
const createWalletPack = useCallback(
|
|
916
932
|
async (name: string): Promise<number> => {
|
|
917
933
|
const { response } = await tgClient.telegramChatWalletPackCreate(
|
|
@@ -1133,16 +1149,18 @@ export function HypurrConnectProvider({
|
|
|
1133
1149
|
const state = randomState();
|
|
1134
1150
|
sessionStorage.setItem(TELEGRAM_AUTH_STATE_KEY, state);
|
|
1135
1151
|
|
|
1136
|
-
const configuredReturnTo = config.telegram
|
|
1152
|
+
const configuredReturnTo = config.telegram?.returnTo;
|
|
1137
1153
|
const returnTo =
|
|
1138
1154
|
typeof configuredReturnTo === "function"
|
|
1139
1155
|
? configuredReturnTo()
|
|
1140
1156
|
: configuredReturnTo || currentReturnTo();
|
|
1141
1157
|
|
|
1142
|
-
const authUrl = new URL(
|
|
1158
|
+
const authUrl = new URL(
|
|
1159
|
+
config.telegram?.authHubUrl || DEFAULT_AUTH_HUB_URL,
|
|
1160
|
+
);
|
|
1143
1161
|
authUrl.searchParams.set("return_to", returnTo);
|
|
1144
1162
|
authUrl.searchParams.set("state", state);
|
|
1145
|
-
authUrl.searchParams.set("scope", normalizeScopes(config.telegram
|
|
1163
|
+
authUrl.searchParams.set("scope", normalizeScopes(config.telegram?.scope));
|
|
1146
1164
|
|
|
1147
1165
|
const width = 520;
|
|
1148
1166
|
const height = 720;
|
|
@@ -1168,9 +1186,9 @@ export function HypurrConnectProvider({
|
|
|
1168
1186
|
|
|
1169
1187
|
window.location.assign(authUrl.toString());
|
|
1170
1188
|
}, [
|
|
1171
|
-
config.telegram
|
|
1172
|
-
config.telegram
|
|
1173
|
-
config.telegram
|
|
1189
|
+
config.telegram?.authHubUrl,
|
|
1190
|
+
config.telegram?.returnTo,
|
|
1191
|
+
config.telegram?.scope,
|
|
1174
1192
|
]);
|
|
1175
1193
|
|
|
1176
1194
|
const connectEoa = useCallback(
|
|
@@ -1333,6 +1351,7 @@ export function HypurrConnectProvider({
|
|
|
1333
1351
|
|
|
1334
1352
|
createWallet,
|
|
1335
1353
|
deleteWallet,
|
|
1354
|
+
renameWallet,
|
|
1336
1355
|
refreshWallets,
|
|
1337
1356
|
|
|
1338
1357
|
packs,
|
|
@@ -1362,10 +1381,6 @@ export function HypurrConnectProvider({
|
|
|
1362
1381
|
agentReady,
|
|
1363
1382
|
clearAgent: handleClearAgent,
|
|
1364
1383
|
|
|
1365
|
-
botId: config.telegram?.botId ?? "",
|
|
1366
|
-
botUsername: config.telegram?.botUsername ?? "",
|
|
1367
|
-
useWidget: config.telegram?.useWidget ?? false,
|
|
1368
|
-
|
|
1369
1384
|
authDataMap,
|
|
1370
1385
|
authToken: tgAuthToken,
|
|
1371
1386
|
telegramRpcOptions,
|
|
@@ -1385,6 +1400,7 @@ export function HypurrConnectProvider({
|
|
|
1385
1400
|
selectWallet,
|
|
1386
1401
|
createWallet,
|
|
1387
1402
|
deleteWallet,
|
|
1403
|
+
renameWallet,
|
|
1388
1404
|
refreshWallets,
|
|
1389
1405
|
packs,
|
|
1390
1406
|
createWalletPack,
|
|
@@ -1407,9 +1423,6 @@ export function HypurrConnectProvider({
|
|
|
1407
1423
|
agent,
|
|
1408
1424
|
agentReady,
|
|
1409
1425
|
handleClearAgent,
|
|
1410
|
-
config.telegram?.botId,
|
|
1411
|
-
config.telegram?.botUsername,
|
|
1412
|
-
config.telegram?.useWidget,
|
|
1413
1426
|
authDataMap,
|
|
1414
1427
|
tgAuthToken,
|
|
1415
1428
|
telegramRpcOptions,
|
package/src/LoginModal.tsx
CHANGED
|
@@ -17,10 +17,14 @@ import { TelegramColorIcon } from "./icons/TelegramColorIcon";
|
|
|
17
17
|
export interface LoginModalProps {
|
|
18
18
|
onConnectWallet: () => void;
|
|
19
19
|
walletIcon?: ReactNode;
|
|
20
|
+
/** CSS color used as the modal/drawer background. Defaults to `rgba(20,20,20,0.95)`. */
|
|
21
|
+
backgroundColor?: string;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const MOBILE_BREAKPOINT = 640;
|
|
23
25
|
|
|
26
|
+
const DEFAULT_BACKGROUND_COLOR = "rgba(20,20,20,0.95)";
|
|
27
|
+
|
|
24
28
|
const btnStyle: CSSProperties = {
|
|
25
29
|
display: "flex",
|
|
26
30
|
height: 53,
|
|
@@ -70,7 +74,6 @@ const modalBoxStyle: CSSProperties = {
|
|
|
70
74
|
overflow: "hidden",
|
|
71
75
|
borderRadius: 12,
|
|
72
76
|
border: "1px solid rgba(255,255,255,0.1)",
|
|
73
|
-
background: "#282828",
|
|
74
77
|
padding: 24,
|
|
75
78
|
};
|
|
76
79
|
|
|
@@ -127,7 +130,11 @@ function HoverButton({
|
|
|
127
130
|
);
|
|
128
131
|
}
|
|
129
132
|
|
|
130
|
-
export function LoginModal({
|
|
133
|
+
export function LoginModal({
|
|
134
|
+
onConnectWallet,
|
|
135
|
+
walletIcon,
|
|
136
|
+
backgroundColor = DEFAULT_BACKGROUND_COLOR,
|
|
137
|
+
}: LoginModalProps) {
|
|
131
138
|
const { loginTelegram, loginModalOpen, closeLoginModal } =
|
|
132
139
|
useHypurrConnectInternal();
|
|
133
140
|
|
|
@@ -174,7 +181,11 @@ export function LoginModal({ onConnectWallet, walletIcon }: LoginModalProps) {
|
|
|
174
181
|
<AnimatePresence>
|
|
175
182
|
{loginModalOpen &&
|
|
176
183
|
(isMobile ? (
|
|
177
|
-
<MobileDrawer
|
|
184
|
+
<MobileDrawer
|
|
185
|
+
key="drawer"
|
|
186
|
+
onClose={closeLoginModal}
|
|
187
|
+
backgroundColor={backgroundColor}
|
|
188
|
+
>
|
|
178
189
|
{modalContent}
|
|
179
190
|
</MobileDrawer>
|
|
180
191
|
) : (
|
|
@@ -198,7 +209,7 @@ export function LoginModal({ onConnectWallet, walletIcon }: LoginModalProps) {
|
|
|
198
209
|
onClick={closeLoginModal}
|
|
199
210
|
>
|
|
200
211
|
<motion.div
|
|
201
|
-
style={modalBoxStyle}
|
|
212
|
+
style={{ ...modalBoxStyle, background: backgroundColor }}
|
|
202
213
|
initial={{ scale: 0.96, opacity: 0, y: 8 }}
|
|
203
214
|
animate={{ scale: 1, opacity: 1, y: 0 }}
|
|
204
215
|
exit={{ scale: 0.96, opacity: 0, y: 8 }}
|
|
@@ -230,7 +241,6 @@ const drawerSheetStyle: CSSProperties = {
|
|
|
230
241
|
borderLeft: "1px solid rgba(255,255,255,0.1)",
|
|
231
242
|
borderRight: "1px solid rgba(255,255,255,0.1)",
|
|
232
243
|
borderTop: "1px solid rgba(255,255,255,0.1)",
|
|
233
|
-
background: "#282828",
|
|
234
244
|
padding: "12px 24px max(24px, env(safe-area-inset-bottom))",
|
|
235
245
|
};
|
|
236
246
|
|
|
@@ -241,7 +251,6 @@ const drawerBgStyle: CSSProperties = {
|
|
|
241
251
|
top: 0,
|
|
242
252
|
bottom: "-100vh",
|
|
243
253
|
zIndex: -1,
|
|
244
|
-
background: "#282828",
|
|
245
254
|
borderTopLeftRadius: 12,
|
|
246
255
|
borderTopRightRadius: 12,
|
|
247
256
|
};
|
|
@@ -263,9 +272,11 @@ const grabHandleStyle: CSSProperties = {
|
|
|
263
272
|
function MobileDrawer({
|
|
264
273
|
children,
|
|
265
274
|
onClose,
|
|
275
|
+
backgroundColor,
|
|
266
276
|
}: {
|
|
267
277
|
children: ReactNode;
|
|
268
278
|
onClose: () => void;
|
|
279
|
+
backgroundColor: string;
|
|
269
280
|
}) {
|
|
270
281
|
const controls = useAnimationControls();
|
|
271
282
|
|
|
@@ -294,7 +305,7 @@ function MobileDrawer({
|
|
|
294
305
|
|
|
295
306
|
<motion.div
|
|
296
307
|
key="drawer-sheet"
|
|
297
|
-
style={drawerSheetStyle}
|
|
308
|
+
style={{ ...drawerSheetStyle, background: backgroundColor }}
|
|
298
309
|
initial={{ y: "100%" }}
|
|
299
310
|
animate={{ y: 0 }}
|
|
300
311
|
exit={{ y: "100%" }}
|
|
@@ -304,7 +315,7 @@ function MobileDrawer({
|
|
|
304
315
|
dragElastic={{ top: 0, bottom: 0.4 }}
|
|
305
316
|
onDragEnd={handleDragEnd}
|
|
306
317
|
>
|
|
307
|
-
<div style={drawerBgStyle} />
|
|
318
|
+
<div style={{ ...drawerBgStyle, background: backgroundColor }} />
|
|
308
319
|
|
|
309
320
|
<div style={grabHandleAreaStyle}>
|
|
310
321
|
<div style={grabHandleStyle} />
|