shogun-button-react 1.3.8 → 1.3.10
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/dist/components/ShogunButton.d.ts +20 -3
- package/dist/components/ShogunButton.js +261 -113
- package/dist/connector.js +29 -11
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/plugins/GunAdvancedPlugin.d.ts +79 -0
- package/dist/plugins/GunAdvancedPlugin.js +498 -0
- package/dist/types/connector-options.d.ts +8 -1
- package/package.json +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import React, { useContext, useState, createContext, useEffect, useRef } from "react";
|
|
1
|
+
import React, { useContext, useState, createContext, useEffect, useRef, } from "react";
|
|
2
2
|
import { Observable } from "rxjs";
|
|
3
|
+
import { GunAdvancedPlugin } from "../plugins/GunAdvancedPlugin";
|
|
3
4
|
import "../types/index.js"; // Import type file to extend definitions
|
|
4
5
|
import "../styles/index.css";
|
|
5
6
|
// Default context
|
|
6
7
|
const defaultShogunContext = {
|
|
7
|
-
|
|
8
|
+
core: null,
|
|
8
9
|
options: {},
|
|
9
10
|
isLoggedIn: false,
|
|
10
11
|
userPub: null,
|
|
@@ -18,13 +19,22 @@ const defaultShogunContext = {
|
|
|
18
19
|
getPlugin: () => undefined,
|
|
19
20
|
exportGunPair: async () => "",
|
|
20
21
|
importGunPair: async () => false,
|
|
22
|
+
gunPlugin: null,
|
|
23
|
+
useGunState: () => ({}),
|
|
24
|
+
useGunCollection: () => ({}),
|
|
25
|
+
useGunConnection: () => ({ isConnected: false, lastSeen: null, error: null }),
|
|
26
|
+
useGunDebug: () => { },
|
|
27
|
+
useGunRealtime: () => ({ data: null, key: null }),
|
|
28
|
+
put: async () => { },
|
|
29
|
+
get: () => null,
|
|
30
|
+
remove: async () => { },
|
|
21
31
|
};
|
|
22
32
|
// Create context using React's createContext directly
|
|
23
33
|
const ShogunContext = createContext(defaultShogunContext);
|
|
24
34
|
// Custom hook to access the context
|
|
25
35
|
export const useShogun = () => useContext(ShogunContext);
|
|
26
36
|
// Provider component
|
|
27
|
-
export function ShogunButtonProvider({ children,
|
|
37
|
+
export function ShogunButtonProvider({ children, core, options, onLoginSuccess, onSignupSuccess, onError, }) {
|
|
28
38
|
// Use React's useState directly
|
|
29
39
|
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
|
30
40
|
const [userPub, setUserPub] = useState(null);
|
|
@@ -32,32 +42,32 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
32
42
|
// Effetto per gestire l'inizializzazione e pulizia
|
|
33
43
|
useEffect(() => {
|
|
34
44
|
var _a, _b;
|
|
35
|
-
if (!
|
|
45
|
+
if (!core)
|
|
36
46
|
return;
|
|
37
47
|
// Verifichiamo se l'utente è già loggato all'inizializzazione
|
|
38
|
-
if (
|
|
39
|
-
const pub = (_b = (_a =
|
|
48
|
+
if (core.isLoggedIn()) {
|
|
49
|
+
const pub = (_b = (_a = core.gun.user()) === null || _a === void 0 ? void 0 : _a.is) === null || _b === void 0 ? void 0 : _b.pub;
|
|
40
50
|
if (pub) {
|
|
41
51
|
setIsLoggedIn(true);
|
|
42
52
|
setUserPub(pub);
|
|
43
|
-
setUsername(pub.slice(0, 8) +
|
|
53
|
+
setUsername(pub.slice(0, 8) + "...");
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
|
-
// Poiché il metodo 'on' non esiste su ShogunCore,
|
|
56
|
+
// Poiché il metodo 'on' non esiste su ShogunCore,
|
|
47
57
|
// gestiamo gli stati direttamente nei metodi di login/logout
|
|
48
|
-
}, [
|
|
58
|
+
}, [core, onLoginSuccess]);
|
|
49
59
|
// RxJS observe method
|
|
50
60
|
const observe = (path) => {
|
|
51
|
-
if (!
|
|
61
|
+
if (!core) {
|
|
52
62
|
return new Observable();
|
|
53
63
|
}
|
|
54
|
-
return
|
|
64
|
+
return core.observe(path);
|
|
55
65
|
};
|
|
56
66
|
// Unified login
|
|
57
67
|
const login = async (method, ...args) => {
|
|
58
68
|
var _a, _b;
|
|
59
69
|
try {
|
|
60
|
-
if (!
|
|
70
|
+
if (!core) {
|
|
61
71
|
throw new Error("SDK not initialized");
|
|
62
72
|
}
|
|
63
73
|
let result;
|
|
@@ -66,16 +76,16 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
66
76
|
switch (method) {
|
|
67
77
|
case "password":
|
|
68
78
|
username = args[0];
|
|
69
|
-
result = await
|
|
79
|
+
result = await core.login(args[0], args[1]);
|
|
70
80
|
break;
|
|
71
81
|
case "pair":
|
|
72
82
|
// New pair authentication method
|
|
73
83
|
const pair = args[0];
|
|
74
|
-
if (!pair || typeof pair !==
|
|
84
|
+
if (!pair || typeof pair !== "object") {
|
|
75
85
|
throw new Error("Invalid pair data provided");
|
|
76
86
|
}
|
|
77
87
|
result = await new Promise((resolve, reject) => {
|
|
78
|
-
|
|
88
|
+
core.gun.user().auth(pair, (ack) => {
|
|
79
89
|
if (ack.err) {
|
|
80
90
|
reject(new Error(`Pair authentication failed: ${ack.err}`));
|
|
81
91
|
return;
|
|
@@ -86,7 +96,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
86
96
|
success: true,
|
|
87
97
|
userPub: pub,
|
|
88
98
|
alias: alias,
|
|
89
|
-
method:
|
|
99
|
+
method: "pair",
|
|
90
100
|
});
|
|
91
101
|
});
|
|
92
102
|
});
|
|
@@ -95,13 +105,13 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
95
105
|
break;
|
|
96
106
|
case "webauthn":
|
|
97
107
|
username = args[0];
|
|
98
|
-
const webauthn =
|
|
108
|
+
const webauthn = core.getPlugin("webauthn");
|
|
99
109
|
if (!webauthn)
|
|
100
110
|
throw new Error("WebAuthn plugin not available");
|
|
101
111
|
result = await webauthn.login(username);
|
|
102
112
|
break;
|
|
103
113
|
case "web3":
|
|
104
|
-
const web3 =
|
|
114
|
+
const web3 = core.getPlugin("web3");
|
|
105
115
|
if (!web3)
|
|
106
116
|
throw new Error("Web3 plugin not available");
|
|
107
117
|
const connectionResult = await web3.connectMetaMask();
|
|
@@ -112,7 +122,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
112
122
|
result = await web3.login(connectionResult.address);
|
|
113
123
|
break;
|
|
114
124
|
case "nostr":
|
|
115
|
-
const nostr =
|
|
125
|
+
const nostr = core.getPlugin("nostr");
|
|
116
126
|
if (!nostr)
|
|
117
127
|
throw new Error("Nostr plugin not available");
|
|
118
128
|
const nostrResult = await nostr.connectBitcoinWallet();
|
|
@@ -126,7 +136,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
126
136
|
result = await nostr.login(pubkey);
|
|
127
137
|
break;
|
|
128
138
|
case "oauth":
|
|
129
|
-
const oauth =
|
|
139
|
+
const oauth = core.getPlugin("oauth");
|
|
130
140
|
if (!oauth)
|
|
131
141
|
throw new Error("OAuth plugin not available");
|
|
132
142
|
const provider = args[0] || "google";
|
|
@@ -140,8 +150,8 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
140
150
|
throw new Error("Unsupported login method");
|
|
141
151
|
}
|
|
142
152
|
if (result.success) {
|
|
143
|
-
const userPub = result.userPub || ((_b = (_a =
|
|
144
|
-
const displayName = result.alias || username || userPub.slice(0, 8) +
|
|
153
|
+
const userPub = result.userPub || ((_b = (_a = core.gun.user()) === null || _a === void 0 ? void 0 : _a.is) === null || _b === void 0 ? void 0 : _b.pub) || "";
|
|
154
|
+
const displayName = result.alias || username || userPub.slice(0, 8) + "...";
|
|
145
155
|
setIsLoggedIn(true);
|
|
146
156
|
setUserPub(userPub);
|
|
147
157
|
setUsername(displayName);
|
|
@@ -165,7 +175,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
165
175
|
const signUp = async (method, ...args) => {
|
|
166
176
|
var _a, _b;
|
|
167
177
|
try {
|
|
168
|
-
if (!
|
|
178
|
+
if (!core) {
|
|
169
179
|
throw new Error("SDK not initialized");
|
|
170
180
|
}
|
|
171
181
|
let result;
|
|
@@ -177,17 +187,17 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
177
187
|
if (args[1] !== args[2]) {
|
|
178
188
|
throw new Error("Passwords do not match");
|
|
179
189
|
}
|
|
180
|
-
result = await
|
|
190
|
+
result = await core.signUp(args[0], args[1]);
|
|
181
191
|
break;
|
|
182
192
|
case "webauthn":
|
|
183
193
|
username = args[0];
|
|
184
|
-
const webauthn =
|
|
194
|
+
const webauthn = core.getPlugin("webauthn");
|
|
185
195
|
if (!webauthn)
|
|
186
196
|
throw new Error("WebAuthn plugin not available");
|
|
187
197
|
result = await webauthn.signUp(username);
|
|
188
198
|
break;
|
|
189
199
|
case "web3":
|
|
190
|
-
const web3 =
|
|
200
|
+
const web3 = core.getPlugin("web3");
|
|
191
201
|
if (!web3)
|
|
192
202
|
throw new Error("Web3 plugin not available");
|
|
193
203
|
const connectionResult = await web3.connectMetaMask();
|
|
@@ -198,7 +208,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
198
208
|
result = await web3.signUp(connectionResult.address);
|
|
199
209
|
break;
|
|
200
210
|
case "nostr":
|
|
201
|
-
const nostr =
|
|
211
|
+
const nostr = core.getPlugin("nostr");
|
|
202
212
|
if (!nostr)
|
|
203
213
|
throw new Error("Nostr plugin not available");
|
|
204
214
|
const nostrResult = await nostr.connectBitcoinWallet();
|
|
@@ -212,7 +222,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
212
222
|
result = await nostr.signUp(pubkey);
|
|
213
223
|
break;
|
|
214
224
|
case "oauth":
|
|
215
|
-
const oauth =
|
|
225
|
+
const oauth = core.getPlugin("oauth");
|
|
216
226
|
if (!oauth)
|
|
217
227
|
throw new Error("OAuth plugin not available");
|
|
218
228
|
const provider = args[0] || "google";
|
|
@@ -226,8 +236,8 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
226
236
|
throw new Error("Unsupported signup method");
|
|
227
237
|
}
|
|
228
238
|
if (result.success) {
|
|
229
|
-
const userPub = result.userPub || ((_b = (_a =
|
|
230
|
-
const displayName = result.alias || username || userPub.slice(0, 8) +
|
|
239
|
+
const userPub = result.userPub || ((_b = (_a = core.gun.user()) === null || _a === void 0 ? void 0 : _a.is) === null || _b === void 0 ? void 0 : _b.pub) || "";
|
|
240
|
+
const displayName = result.alias || username || userPub.slice(0, 8) + "...";
|
|
231
241
|
setIsLoggedIn(true);
|
|
232
242
|
setUserPub(userPub);
|
|
233
243
|
setUsername(displayName);
|
|
@@ -249,7 +259,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
249
259
|
};
|
|
250
260
|
// Logout
|
|
251
261
|
const logout = () => {
|
|
252
|
-
|
|
262
|
+
core.logout();
|
|
253
263
|
setIsLoggedIn(false);
|
|
254
264
|
setUserPub(null);
|
|
255
265
|
setUsername(null);
|
|
@@ -259,7 +269,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
259
269
|
};
|
|
260
270
|
// Implementazione del metodo setProvider
|
|
261
271
|
const setProvider = (provider) => {
|
|
262
|
-
if (!
|
|
272
|
+
if (!core) {
|
|
263
273
|
return false;
|
|
264
274
|
}
|
|
265
275
|
try {
|
|
@@ -267,12 +277,12 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
267
277
|
if (provider && provider.connection && provider.connection.url) {
|
|
268
278
|
newProviderUrl = provider.connection.url;
|
|
269
279
|
}
|
|
270
|
-
else if (typeof provider ===
|
|
280
|
+
else if (typeof provider === "string") {
|
|
271
281
|
newProviderUrl = provider;
|
|
272
282
|
}
|
|
273
283
|
if (newProviderUrl) {
|
|
274
|
-
if (typeof
|
|
275
|
-
return
|
|
284
|
+
if (typeof core.setRpcUrl === "function") {
|
|
285
|
+
return core.setRpcUrl(newProviderUrl);
|
|
276
286
|
}
|
|
277
287
|
}
|
|
278
288
|
return false;
|
|
@@ -283,14 +293,14 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
283
293
|
}
|
|
284
294
|
};
|
|
285
295
|
const hasPlugin = (name) => {
|
|
286
|
-
return
|
|
296
|
+
return core ? core.hasPlugin(name) : false;
|
|
287
297
|
};
|
|
288
298
|
const getPlugin = (name) => {
|
|
289
|
-
return
|
|
299
|
+
return core ? core.getPlugin(name) : undefined;
|
|
290
300
|
};
|
|
291
301
|
// Export Gun pair functionality
|
|
292
302
|
const exportGunPair = async (password) => {
|
|
293
|
-
if (!
|
|
303
|
+
if (!core) {
|
|
294
304
|
throw new Error("SDK not initialized");
|
|
295
305
|
}
|
|
296
306
|
if (!isLoggedIn) {
|
|
@@ -320,7 +330,7 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
320
330
|
};
|
|
321
331
|
// Import Gun pair functionality
|
|
322
332
|
const importGunPair = async (pairData, password) => {
|
|
323
|
-
if (!
|
|
333
|
+
if (!core) {
|
|
324
334
|
throw new Error("SDK not initialized");
|
|
325
335
|
}
|
|
326
336
|
try {
|
|
@@ -350,23 +360,111 @@ export function ShogunButtonProvider({ children, sdk, options, onLoginSuccess, o
|
|
|
350
360
|
throw new Error(`Failed to import Gun pair: ${error.message}`);
|
|
351
361
|
}
|
|
352
362
|
};
|
|
363
|
+
// Inizializza il plugin
|
|
364
|
+
const gunPlugin = React.useMemo(() => {
|
|
365
|
+
if (!core)
|
|
366
|
+
return null;
|
|
367
|
+
return new GunAdvancedPlugin(core, {
|
|
368
|
+
enableDebug: options.enableGunDebug !== false,
|
|
369
|
+
enableConnectionMonitoring: options.enableConnectionMonitoring !== false,
|
|
370
|
+
defaultPageSize: options.defaultPageSize || 20,
|
|
371
|
+
connectionTimeout: options.connectionTimeout || 10000,
|
|
372
|
+
debounceInterval: options.debounceInterval || 100,
|
|
373
|
+
});
|
|
374
|
+
}, [core, options]);
|
|
375
|
+
// Effetto per pulizia del plugin
|
|
376
|
+
React.useEffect(() => {
|
|
377
|
+
return () => {
|
|
378
|
+
if (gunPlugin) {
|
|
379
|
+
gunPlugin.cleanup();
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}, [gunPlugin]);
|
|
383
|
+
// Crea gli hook del plugin
|
|
384
|
+
const pluginHooks = React.useMemo(() => {
|
|
385
|
+
if (!gunPlugin)
|
|
386
|
+
return {};
|
|
387
|
+
return gunPlugin.createHooks();
|
|
388
|
+
}, [gunPlugin]);
|
|
389
|
+
// Create a properly typed context value
|
|
390
|
+
const contextValue = React.useMemo(() => ({
|
|
391
|
+
core,
|
|
392
|
+
options,
|
|
393
|
+
isLoggedIn,
|
|
394
|
+
userPub,
|
|
395
|
+
username,
|
|
396
|
+
login,
|
|
397
|
+
signUp,
|
|
398
|
+
logout,
|
|
399
|
+
observe,
|
|
400
|
+
hasPlugin,
|
|
401
|
+
getPlugin,
|
|
402
|
+
exportGunPair,
|
|
403
|
+
importGunPair,
|
|
404
|
+
setProvider,
|
|
405
|
+
gunPlugin,
|
|
406
|
+
// Ensure all required hooks are present with proper fallbacks
|
|
407
|
+
useGunState: pluginHooks.useGunState ||
|
|
408
|
+
(() => ({
|
|
409
|
+
data: null,
|
|
410
|
+
isLoading: false,
|
|
411
|
+
error: null,
|
|
412
|
+
update: async () => { },
|
|
413
|
+
set: async () => { },
|
|
414
|
+
remove: async () => { },
|
|
415
|
+
refresh: () => { },
|
|
416
|
+
})),
|
|
417
|
+
useGunCollection: pluginHooks.useGunCollection ||
|
|
418
|
+
(() => ({
|
|
419
|
+
items: [],
|
|
420
|
+
currentPage: 0,
|
|
421
|
+
totalPages: 0,
|
|
422
|
+
hasNextPage: false,
|
|
423
|
+
hasPrevPage: false,
|
|
424
|
+
nextPage: () => { },
|
|
425
|
+
prevPage: () => { },
|
|
426
|
+
goToPage: () => { },
|
|
427
|
+
isLoading: false,
|
|
428
|
+
error: null,
|
|
429
|
+
refresh: () => { },
|
|
430
|
+
addItem: async () => { },
|
|
431
|
+
updateItem: async () => { },
|
|
432
|
+
removeItem: async () => { },
|
|
433
|
+
})),
|
|
434
|
+
useGunConnection: pluginHooks.useGunConnection ||
|
|
435
|
+
(() => ({
|
|
436
|
+
isConnected: false,
|
|
437
|
+
lastSeen: null,
|
|
438
|
+
error: null,
|
|
439
|
+
})),
|
|
440
|
+
useGunDebug: pluginHooks.useGunDebug || (() => { }),
|
|
441
|
+
useGunRealtime: pluginHooks.useGunRealtime ||
|
|
442
|
+
(() => ({
|
|
443
|
+
data: null,
|
|
444
|
+
key: null,
|
|
445
|
+
})),
|
|
446
|
+
put: (gunPlugin === null || gunPlugin === void 0 ? void 0 : gunPlugin.put.bind(gunPlugin)) || (async () => { }),
|
|
447
|
+
get: (gunPlugin === null || gunPlugin === void 0 ? void 0 : gunPlugin.get.bind(gunPlugin)) || (() => null),
|
|
448
|
+
remove: (gunPlugin === null || gunPlugin === void 0 ? void 0 : gunPlugin.remove.bind(gunPlugin)) || (async () => { }),
|
|
449
|
+
}), [
|
|
450
|
+
core,
|
|
451
|
+
options,
|
|
452
|
+
isLoggedIn,
|
|
453
|
+
userPub,
|
|
454
|
+
username,
|
|
455
|
+
login,
|
|
456
|
+
signUp,
|
|
457
|
+
logout,
|
|
458
|
+
observe,
|
|
459
|
+
hasPlugin,
|
|
460
|
+
getPlugin,
|
|
461
|
+
exportGunPair,
|
|
462
|
+
importGunPair,
|
|
463
|
+
gunPlugin,
|
|
464
|
+
pluginHooks,
|
|
465
|
+
]);
|
|
353
466
|
// Provide the context value to children
|
|
354
|
-
return (React.createElement(ShogunContext.Provider, { value:
|
|
355
|
-
sdk,
|
|
356
|
-
options,
|
|
357
|
-
isLoggedIn,
|
|
358
|
-
userPub,
|
|
359
|
-
username,
|
|
360
|
-
login,
|
|
361
|
-
signUp,
|
|
362
|
-
logout,
|
|
363
|
-
observe,
|
|
364
|
-
setProvider,
|
|
365
|
-
hasPlugin,
|
|
366
|
-
getPlugin,
|
|
367
|
-
exportGunPair,
|
|
368
|
-
importGunPair,
|
|
369
|
-
} }, children));
|
|
467
|
+
return (React.createElement(ShogunContext.Provider, { value: contextValue }, children));
|
|
370
468
|
}
|
|
371
469
|
// SVG Icons Components
|
|
372
470
|
const WalletIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
@@ -414,7 +512,7 @@ const ExportIcon = () => (React.createElement("svg", { xmlns: "http://www.w3.org
|
|
|
414
512
|
// Component for Shogun login button
|
|
415
513
|
export const ShogunButton = (() => {
|
|
416
514
|
const Button = () => {
|
|
417
|
-
const { isLoggedIn, username, logout, login, signUp,
|
|
515
|
+
const { isLoggedIn, username, logout, login, signUp, core, options, exportGunPair, importGunPair, } = useShogun();
|
|
418
516
|
// Form states
|
|
419
517
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
|
420
518
|
const [formUsername, setFormUsername] = useState("");
|
|
@@ -439,14 +537,15 @@ export const ShogunButton = (() => {
|
|
|
439
537
|
// Handle click outside to close dropdown
|
|
440
538
|
useEffect(() => {
|
|
441
539
|
const handleClickOutside = (event) => {
|
|
442
|
-
if (dropdownRef.current &&
|
|
540
|
+
if (dropdownRef.current &&
|
|
541
|
+
!dropdownRef.current.contains(event.target)) {
|
|
443
542
|
setDropdownOpen(false);
|
|
444
543
|
}
|
|
445
544
|
};
|
|
446
545
|
if (dropdownOpen) {
|
|
447
|
-
document.addEventListener(
|
|
546
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
448
547
|
return () => {
|
|
449
|
-
document.removeEventListener(
|
|
548
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
450
549
|
};
|
|
451
550
|
}
|
|
452
551
|
}, [dropdownOpen]);
|
|
@@ -510,8 +609,8 @@ export const ShogunButton = (() => {
|
|
|
510
609
|
if (formMode === "signup") {
|
|
511
610
|
const result = await signUp("password", formUsername, formPassword, formPasswordConfirm);
|
|
512
611
|
if (result && result.success) {
|
|
513
|
-
if (
|
|
514
|
-
await
|
|
612
|
+
if (core === null || core === void 0 ? void 0 : core.gundb) {
|
|
613
|
+
await core.gundb.setPasswordHint(formUsername, formPassword, formHint, [formSecurityQuestion], [formSecurityAnswer]);
|
|
515
614
|
}
|
|
516
615
|
setModalIsOpen(false);
|
|
517
616
|
}
|
|
@@ -532,7 +631,7 @@ export const ShogunButton = (() => {
|
|
|
532
631
|
};
|
|
533
632
|
const handleWeb3Auth = () => handleAuth("web3");
|
|
534
633
|
const handleWebAuthnAuth = () => {
|
|
535
|
-
if (!(
|
|
634
|
+
if (!(core === null || core === void 0 ? void 0 : core.hasPlugin("webauthn"))) {
|
|
536
635
|
setError("WebAuthn is not supported in your browser");
|
|
537
636
|
return;
|
|
538
637
|
}
|
|
@@ -544,10 +643,10 @@ export const ShogunButton = (() => {
|
|
|
544
643
|
setError("");
|
|
545
644
|
setLoading(true);
|
|
546
645
|
try {
|
|
547
|
-
if (!(
|
|
646
|
+
if (!(core === null || core === void 0 ? void 0 : core.gundb)) {
|
|
548
647
|
throw new Error("SDK not ready");
|
|
549
648
|
}
|
|
550
|
-
const result = await
|
|
649
|
+
const result = await core.gundb.forgotPassword(formUsername, [
|
|
551
650
|
formSecurityAnswer,
|
|
552
651
|
]);
|
|
553
652
|
if (result.success && result.hint) {
|
|
@@ -644,27 +743,35 @@ export const ShogunButton = (() => {
|
|
|
644
743
|
};
|
|
645
744
|
// Add buttons for both login and signup for alternative auth methods
|
|
646
745
|
const renderAuthOptions = () => (React.createElement("div", { className: "shogun-auth-options" },
|
|
647
|
-
options.showMetamask !== false && (
|
|
746
|
+
options.showMetamask !== false && (core === null || core === void 0 ? void 0 : core.hasPlugin("web3")) && (React.createElement("div", { className: "shogun-auth-option-group" },
|
|
648
747
|
React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: () => handleAuth("web3"), disabled: loading },
|
|
649
748
|
React.createElement(WalletIcon, null),
|
|
650
|
-
formMode === "login"
|
|
651
|
-
|
|
749
|
+
formMode === "login"
|
|
750
|
+
? "Login with MetaMask"
|
|
751
|
+
: "Signup with MetaMask"))),
|
|
752
|
+
options.showWebauthn !== false && (core === null || core === void 0 ? void 0 : core.hasPlugin("webauthn")) && (React.createElement("div", { className: "shogun-auth-option-group" },
|
|
652
753
|
React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: handleWebAuthnAuth, disabled: loading },
|
|
653
754
|
React.createElement(WebAuthnIcon, null),
|
|
654
|
-
formMode === "login"
|
|
655
|
-
|
|
755
|
+
formMode === "login"
|
|
756
|
+
? "Login with WebAuthn"
|
|
757
|
+
: "Signup with WebAuthn"))),
|
|
758
|
+
options.showNostr !== false && (core === null || core === void 0 ? void 0 : core.hasPlugin("nostr")) && (React.createElement("div", { className: "shogun-auth-option-group" },
|
|
656
759
|
React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: () => handleAuth("nostr"), disabled: loading },
|
|
657
760
|
React.createElement(NostrIcon, null),
|
|
658
761
|
formMode === "login" ? "Login with Nostr" : "Signup with Nostr"))),
|
|
659
|
-
options.showOauth !== false && (
|
|
762
|
+
options.showOauth !== false && (core === null || core === void 0 ? void 0 : core.hasPlugin("oauth")) && (React.createElement("div", { className: "shogun-auth-option-group" },
|
|
660
763
|
React.createElement("button", { type: "button", className: "shogun-auth-option-button shogun-google-button", onClick: () => handleAuth("oauth", "google"), disabled: loading },
|
|
661
764
|
React.createElement(GoogleIcon, null),
|
|
662
|
-
formMode === "login"
|
|
765
|
+
formMode === "login"
|
|
766
|
+
? "Login with Google"
|
|
767
|
+
: "Signup with Google"))),
|
|
663
768
|
React.createElement("div", { className: "shogun-divider" },
|
|
664
769
|
React.createElement("span", null, "or")),
|
|
665
770
|
React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: () => setAuthView("password"), disabled: loading },
|
|
666
771
|
React.createElement(LockIcon, null),
|
|
667
|
-
formMode === "login"
|
|
772
|
+
formMode === "login"
|
|
773
|
+
? "Login with Password"
|
|
774
|
+
: "Signup with Password"),
|
|
668
775
|
formMode === "login" && (React.createElement("button", { type: "button", className: "shogun-auth-option-button", onClick: () => setAuthView("import"), disabled: loading },
|
|
669
776
|
React.createElement(ImportIcon, null),
|
|
670
777
|
"Import Gun Pair"))));
|
|
@@ -711,11 +818,25 @@ export const ShogunButton = (() => {
|
|
|
711
818
|
: "Already have an account? Log in"),
|
|
712
819
|
formMode === "login" && (React.createElement("button", { type: "button", className: "shogun-toggle-mode", onClick: () => setAuthView("recover"), disabled: loading }, "Forgot password?")))));
|
|
713
820
|
const renderWebAuthnUsernameForm = () => (React.createElement("div", { className: "shogun-auth-form" },
|
|
714
|
-
React.createElement("h3", null, formMode === "login"
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
821
|
+
React.createElement("h3", null, formMode === "login"
|
|
822
|
+
? "Login with WebAuthn"
|
|
823
|
+
: "Sign Up with WebAuthn"),
|
|
824
|
+
React.createElement("div", { style: {
|
|
825
|
+
backgroundColor: "#f0f9ff",
|
|
826
|
+
padding: "12px",
|
|
827
|
+
borderRadius: "8px",
|
|
828
|
+
marginBottom: "16px",
|
|
829
|
+
border: "1px solid #0ea5e9",
|
|
830
|
+
} },
|
|
831
|
+
React.createElement("p", { style: {
|
|
832
|
+
fontSize: "14px",
|
|
833
|
+
color: "#0c4a6e",
|
|
834
|
+
margin: "0",
|
|
835
|
+
fontWeight: "500",
|
|
836
|
+
} }, "\uD83D\uDD11 WebAuthn Authentication"),
|
|
837
|
+
React.createElement("p", { style: { fontSize: "13px", color: "#075985", margin: "4px 0 0 0" } },
|
|
838
|
+
"Please enter your username to continue with WebAuthn",
|
|
839
|
+
" ",
|
|
719
840
|
formMode === "login" ? "login" : "registration",
|
|
720
841
|
".")),
|
|
721
842
|
React.createElement("div", { className: "shogun-form-group" },
|
|
@@ -753,9 +874,20 @@ export const ShogunButton = (() => {
|
|
|
753
874
|
} }, "Back to Login")));
|
|
754
875
|
const renderExportForm = () => (React.createElement("div", { className: "shogun-auth-form" },
|
|
755
876
|
React.createElement("h3", null, "Export Gun Pair"),
|
|
756
|
-
React.createElement("div", { style: {
|
|
757
|
-
|
|
758
|
-
|
|
877
|
+
React.createElement("div", { style: {
|
|
878
|
+
backgroundColor: "#f0f9ff",
|
|
879
|
+
padding: "12px",
|
|
880
|
+
borderRadius: "8px",
|
|
881
|
+
marginBottom: "16px",
|
|
882
|
+
border: "1px solid #0ea5e9",
|
|
883
|
+
} },
|
|
884
|
+
React.createElement("p", { style: {
|
|
885
|
+
fontSize: "14px",
|
|
886
|
+
color: "#0c4a6e",
|
|
887
|
+
margin: "0",
|
|
888
|
+
fontWeight: "500",
|
|
889
|
+
} }, "\uD83D\uDD12 Backup Your Account"),
|
|
890
|
+
React.createElement("p", { style: { fontSize: "13px", color: "#075985", margin: "4px 0 0 0" } }, "Export your Gun pair to backup your account. You can use this to login from another device or restore access if needed.")),
|
|
759
891
|
React.createElement("div", { className: "shogun-form-group" },
|
|
760
892
|
React.createElement("label", { htmlFor: "exportPassword" },
|
|
761
893
|
React.createElement(LockIcon, null),
|
|
@@ -764,23 +896,23 @@ export const ShogunButton = (() => {
|
|
|
764
896
|
exportedPair && (React.createElement("div", { className: "shogun-form-group" },
|
|
765
897
|
React.createElement("label", null, "Your Gun Pair (copy this safely):"),
|
|
766
898
|
showCopySuccess && (React.createElement("div", { style: {
|
|
767
|
-
backgroundColor:
|
|
768
|
-
color:
|
|
769
|
-
padding:
|
|
770
|
-
borderRadius:
|
|
771
|
-
marginBottom:
|
|
772
|
-
fontSize:
|
|
773
|
-
border:
|
|
899
|
+
backgroundColor: "#dcfce7",
|
|
900
|
+
color: "#166534",
|
|
901
|
+
padding: "8px 12px",
|
|
902
|
+
borderRadius: "4px",
|
|
903
|
+
marginBottom: "8px",
|
|
904
|
+
fontSize: "14px",
|
|
905
|
+
border: "1px solid #22c55e",
|
|
774
906
|
} }, "\u2705 Copied to clipboard successfully!")),
|
|
775
907
|
React.createElement("textarea", { value: exportedPair, readOnly: true, rows: 6, style: {
|
|
776
|
-
fontFamily:
|
|
777
|
-
fontSize:
|
|
778
|
-
width:
|
|
779
|
-
padding:
|
|
780
|
-
border:
|
|
781
|
-
borderRadius:
|
|
908
|
+
fontFamily: "monospace",
|
|
909
|
+
fontSize: "12px",
|
|
910
|
+
width: "100%",
|
|
911
|
+
padding: "8px",
|
|
912
|
+
border: "1px solid #ccc",
|
|
913
|
+
borderRadius: "4px",
|
|
782
914
|
} }),
|
|
783
|
-
!navigator.clipboard && (React.createElement("p", { style: { fontSize:
|
|
915
|
+
!navigator.clipboard && (React.createElement("p", { style: { fontSize: "12px", color: "#666", marginTop: "8px" } }, "\u26A0\uFE0F Auto-copy not available. Please manually copy the text above.")))),
|
|
784
916
|
React.createElement("button", { type: "button", className: "shogun-submit-button", onClick: handleExportPair, disabled: loading }, loading ? "Exporting..." : "Export Pair"),
|
|
785
917
|
React.createElement("div", { className: "shogun-form-footer" },
|
|
786
918
|
React.createElement("button", { className: "shogun-toggle-mode", onClick: () => {
|
|
@@ -798,20 +930,31 @@ export const ShogunButton = (() => {
|
|
|
798
930
|
}, disabled: loading }, "Back"))));
|
|
799
931
|
const renderImportForm = () => (React.createElement("div", { className: "shogun-auth-form" },
|
|
800
932
|
React.createElement("h3", null, "Import Gun Pair"),
|
|
801
|
-
React.createElement("div", { style: {
|
|
802
|
-
|
|
803
|
-
|
|
933
|
+
React.createElement("div", { style: {
|
|
934
|
+
backgroundColor: "#fef3c7",
|
|
935
|
+
padding: "12px",
|
|
936
|
+
borderRadius: "8px",
|
|
937
|
+
marginBottom: "16px",
|
|
938
|
+
border: "1px solid #f59e0b",
|
|
939
|
+
} },
|
|
940
|
+
React.createElement("p", { style: {
|
|
941
|
+
fontSize: "14px",
|
|
942
|
+
color: "#92400e",
|
|
943
|
+
margin: "0",
|
|
944
|
+
fontWeight: "500",
|
|
945
|
+
} }, "\uD83D\uDD11 Restore Your Account"),
|
|
946
|
+
React.createElement("p", { style: { fontSize: "13px", color: "#a16207", margin: "4px 0 0 0" } }, "Import a Gun pair to login with your existing account from another device. Make sure you have your backup data ready.")),
|
|
804
947
|
React.createElement("div", { className: "shogun-form-group" },
|
|
805
948
|
React.createElement("label", { htmlFor: "importPairData" },
|
|
806
949
|
React.createElement(ImportIcon, null),
|
|
807
950
|
React.createElement("span", null, "Gun Pair Data")),
|
|
808
951
|
React.createElement("textarea", { id: "importPairData", value: importPairData, onChange: (e) => setImportPairData(e.target.value), disabled: loading, placeholder: "Paste your Gun pair JSON here...", rows: 6, style: {
|
|
809
|
-
fontFamily:
|
|
810
|
-
fontSize:
|
|
811
|
-
width:
|
|
812
|
-
padding:
|
|
813
|
-
border:
|
|
814
|
-
borderRadius:
|
|
952
|
+
fontFamily: "monospace",
|
|
953
|
+
fontSize: "12px",
|
|
954
|
+
width: "100%",
|
|
955
|
+
padding: "8px",
|
|
956
|
+
border: "1px solid #ccc",
|
|
957
|
+
borderRadius: "4px",
|
|
815
958
|
} })),
|
|
816
959
|
React.createElement("div", { className: "shogun-form-group" },
|
|
817
960
|
React.createElement("label", { htmlFor: "importPassword" },
|
|
@@ -819,16 +962,20 @@ export const ShogunButton = (() => {
|
|
|
819
962
|
React.createElement("span", null, "Decryption Password (if encrypted)")),
|
|
820
963
|
React.createElement("input", { type: "password", id: "importPassword", value: importPassword, onChange: (e) => setImportPassword(e.target.value), disabled: loading, placeholder: "Enter password if pair was encrypted" })),
|
|
821
964
|
showImportSuccess && (React.createElement("div", { style: {
|
|
822
|
-
backgroundColor:
|
|
823
|
-
color:
|
|
824
|
-
padding:
|
|
825
|
-
borderRadius:
|
|
826
|
-
marginBottom:
|
|
827
|
-
fontSize:
|
|
828
|
-
border:
|
|
829
|
-
textAlign:
|
|
965
|
+
backgroundColor: "#dcfce7",
|
|
966
|
+
color: "#166534",
|
|
967
|
+
padding: "12px",
|
|
968
|
+
borderRadius: "8px",
|
|
969
|
+
marginBottom: "16px",
|
|
970
|
+
fontSize: "14px",
|
|
971
|
+
border: "1px solid #22c55e",
|
|
972
|
+
textAlign: "center",
|
|
830
973
|
} }, "\u2705 Pair imported successfully! Logging you in...")),
|
|
831
|
-
React.createElement("button", { type: "button", className: "shogun-submit-button", onClick: handleImportPair, disabled: loading || showImportSuccess }, loading
|
|
974
|
+
React.createElement("button", { type: "button", className: "shogun-submit-button", onClick: handleImportPair, disabled: loading || showImportSuccess }, loading
|
|
975
|
+
? "Importing..."
|
|
976
|
+
: showImportSuccess
|
|
977
|
+
? "Success!"
|
|
978
|
+
: "Import and Login"),
|
|
832
979
|
React.createElement("div", { className: "shogun-form-footer" },
|
|
833
980
|
React.createElement("button", { className: "shogun-toggle-mode", onClick: () => {
|
|
834
981
|
setAuthView("options");
|
|
@@ -873,7 +1020,8 @@ export const ShogunButton = (() => {
|
|
|
873
1020
|
authView === "showHint" && renderHint(),
|
|
874
1021
|
authView === "export" && renderExportForm(),
|
|
875
1022
|
authView === "import" && renderImportForm(),
|
|
876
|
-
authView === "webauthn-username" &&
|
|
1023
|
+
authView === "webauthn-username" &&
|
|
1024
|
+
renderWebAuthnUsernameForm()))))));
|
|
877
1025
|
};
|
|
878
1026
|
Button.displayName = "ShogunButton";
|
|
879
1027
|
return Object.assign(Button, {
|