shogun-button-react 1.10.3 → 1.11.1
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/CHANGELOG.md +1 -20
- package/README.md +423 -225
- package/dist/components/ShogunButton.d.ts +20 -5
- package/dist/components/ShogunButton.js +440 -488
- package/dist/connector.js +75 -45
- package/dist/dist/styles/index.css +0 -26
- package/dist/index.d.ts +6 -3
- package/dist/index.js +10 -9
- package/dist/plugins/GunAdvancedPlugin.d.ts +81 -0
- package/dist/plugins/GunAdvancedPlugin.js +501 -0
- package/dist/styles/index.css +0 -26
- package/dist/types/connector-options.d.ts +20 -4
- package/dist/types/connector-options.js +1 -2
- package/package.json +4 -3
- package/src/styles/index.css +0 -26
package/README.md
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
# Shogun Button React
|
|
2
2
|
|
|
3
|
-
A React component library for seamless integration of Shogun authentication into your applications. This library provides a simple yet powerful way to add
|
|
3
|
+
A comprehensive React component library for seamless integration of Shogun authentication into your applications. This library provides a simple yet powerful way to add multi-method authentication, account management, and real-time data synchronization to your React applications.
|
|
4
4
|
|
|
5
|
-
## Features
|
|
5
|
+
## ✨ Features
|
|
6
6
|
|
|
7
|
-
- 🚀 Easy
|
|
8
|
-
- 🎨 Customizable UI
|
|
9
|
-
- 🔒
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
7
|
+
- 🚀 **Easy Integration** - Simple setup with minimal configuration
|
|
8
|
+
- 🎨 **Customizable UI** - Modern, responsive design with dark mode support
|
|
9
|
+
- 🔒 **Multi-Authentication** - Support for Password, MetaMask, WebAuthn, Nostr, and OAuth
|
|
10
|
+
- 🔑 **Account Management** - Export/import Gun pairs for account backup and recovery
|
|
11
|
+
- 📱 **Responsive Design** - Works seamlessly across all device sizes
|
|
12
|
+
- 🌍 **TypeScript Support** - Full type safety and IntelliSense support
|
|
13
|
+
- 🔌 **Plugin System** - Advanced Gun operations with custom hooks
|
|
14
|
+
- 📊 **Real-time Data** - Reactive data synchronization with RxJS observables
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## 🚀 Quick Start
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
17
19
|
|
|
18
20
|
```bash
|
|
19
21
|
npm install shogun-button-react
|
|
@@ -21,61 +23,47 @@ npm install shogun-button-react
|
|
|
21
23
|
yarn add shogun-button-react
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
### Basic Usage
|
|
25
27
|
|
|
26
28
|
```tsx
|
|
27
29
|
import React from "react";
|
|
28
|
-
import {
|
|
29
|
-
ShogunButton,
|
|
30
|
-
ShogunButtonProvider,
|
|
31
|
-
shogunConnector,
|
|
32
|
-
} from "shogun-button-react";
|
|
30
|
+
import { ShogunButton, ShogunButtonProvider, shogunConnector } from "shogun-button-react";
|
|
33
31
|
import "shogun-button-react/styles.css";
|
|
34
32
|
|
|
35
33
|
function App() {
|
|
36
|
-
const {
|
|
37
|
-
appName: "My App",
|
|
38
|
-
|
|
39
|
-
appUrl: "https://myapp.com",
|
|
40
|
-
appIcon: "https://myapp.com/icon.png",
|
|
41
|
-
// Enable authentication methods
|
|
34
|
+
const { core, options } = shogunConnector({
|
|
35
|
+
appName: "My Awesome App",
|
|
36
|
+
// Enable specific authentication methods
|
|
42
37
|
showMetamask: true,
|
|
43
38
|
showWebauthn: true,
|
|
44
39
|
showNostr: true,
|
|
45
40
|
showOauth: true,
|
|
46
|
-
//
|
|
47
|
-
peers: [
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
providers: {
|
|
51
|
-
google: {
|
|
52
|
-
clientId: "YOUR_GOOGLE_CLIENT_ID",
|
|
53
|
-
redirectUri: "http://localhost:3000/auth/callback",
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
},
|
|
41
|
+
// Optional peers
|
|
42
|
+
peers: [
|
|
43
|
+
"https://gun-manhattan.herokuapp.com/gun"
|
|
44
|
+
],
|
|
57
45
|
});
|
|
58
46
|
|
|
59
47
|
return (
|
|
60
48
|
<ShogunButtonProvider
|
|
61
|
-
|
|
49
|
+
core={core}
|
|
62
50
|
options={options}
|
|
63
51
|
onLoginSuccess={(data) => {
|
|
64
52
|
console.log("Login successful!", data);
|
|
65
53
|
}}
|
|
66
54
|
onSignupSuccess={(data) => {
|
|
67
|
-
console.log("
|
|
55
|
+
console.log("Account created successfully!", data);
|
|
68
56
|
}}
|
|
69
57
|
onError={(error) => {
|
|
70
|
-
console.error("
|
|
71
|
-
}}
|
|
72
|
-
onLogout={() => {
|
|
73
|
-
console.log("User logged out");
|
|
58
|
+
console.error("Authentication error:", error);
|
|
74
59
|
}}
|
|
75
60
|
>
|
|
76
|
-
<div>
|
|
77
|
-
<
|
|
78
|
-
|
|
61
|
+
<div className="app">
|
|
62
|
+
<header>
|
|
63
|
+
<h1>Welcome to My Awesome App</h1>
|
|
64
|
+
<ShogunButton />
|
|
65
|
+
</header>
|
|
66
|
+
<main>{/* Your app content */}</main>
|
|
79
67
|
</div>
|
|
80
68
|
</ShogunButtonProvider>
|
|
81
69
|
);
|
|
@@ -84,7 +72,44 @@ function App() {
|
|
|
84
72
|
export default App;
|
|
85
73
|
```
|
|
86
74
|
|
|
87
|
-
##
|
|
75
|
+
## 🔧 Advanced Configuration
|
|
76
|
+
|
|
77
|
+
### Custom Authentication Options
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
const { core, options } = shogunConnector({
|
|
81
|
+
appName: "My App",
|
|
82
|
+
|
|
83
|
+
// Toggle authentication methods in the UI
|
|
84
|
+
showMetamask: true,
|
|
85
|
+
showWebauthn: true,
|
|
86
|
+
showNostr: true,
|
|
87
|
+
showOauth: true,
|
|
88
|
+
|
|
89
|
+
// Network configuration
|
|
90
|
+
peers: [
|
|
91
|
+
"https://gun-manhattan.herokuapp.com/gun"
|
|
92
|
+
],
|
|
93
|
+
|
|
94
|
+
// OAuth provider configuration (optional)
|
|
95
|
+
oauth: {
|
|
96
|
+
providers: {
|
|
97
|
+
google: {
|
|
98
|
+
clientId: "your-google-client-id",
|
|
99
|
+
redirectUri: "https://myapp.com/auth/callback"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
// Gun Advanced Plugin configuration
|
|
105
|
+
enableGunDebug: true,
|
|
106
|
+
enableConnectionMonitoring: true,
|
|
107
|
+
defaultPageSize: 20,
|
|
108
|
+
connectionTimeout: 10000,
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 🎯 API Reference
|
|
88
113
|
|
|
89
114
|
### ShogunButtonProvider
|
|
90
115
|
|
|
@@ -92,130 +117,366 @@ The provider component that supplies Shogun context to your application.
|
|
|
92
117
|
|
|
93
118
|
#### Props
|
|
94
119
|
|
|
95
|
-
| Name
|
|
96
|
-
|
|
97
|
-
|
|
|
98
|
-
| options
|
|
99
|
-
| onLoginSuccess
|
|
100
|
-
| onSignupSuccess | (data:
|
|
101
|
-
| onError
|
|
102
|
-
|
|
120
|
+
| Name | Type | Description | Required |
|
|
121
|
+
|------|------|-------------|----------|
|
|
122
|
+
| `core` | `ShogunCore` | Shogun SDK instance created by `shogunConnector` | ✅ |
|
|
123
|
+
| `options` | `ShogunConnectorOptions` | Configuration options | ✅ |
|
|
124
|
+
| `onLoginSuccess` | `(data: AuthData) => void` | Callback fired on successful login | ❌ |
|
|
125
|
+
| `onSignupSuccess` | `(data: AuthData) => void` | Callback fired on successful signup | ❌ |
|
|
126
|
+
| `onError` | `(error: string) => void` | Callback fired when an error occurs | ❌ |
|
|
127
|
+
|
|
128
|
+
#### AuthData Interface
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
interface AuthData {
|
|
132
|
+
userPub: string; // User's public key
|
|
133
|
+
username: string; // Display name
|
|
134
|
+
password?: string; // Password (if applicable)
|
|
135
|
+
authMethod?: "password" | "web3" | "webauthn" | "nostr" | "oauth" | "pair";
|
|
136
|
+
}
|
|
137
|
+
```
|
|
103
138
|
|
|
104
139
|
### ShogunButton
|
|
105
140
|
|
|
106
|
-
The main button component
|
|
141
|
+
The main button component that provides a complete authentication UI with modal dialogs for login, signup, and account management.
|
|
142
|
+
|
|
143
|
+
**Features:**
|
|
144
|
+
- Multi-method authentication selection
|
|
145
|
+
- Password-based login/signup with recovery
|
|
146
|
+
- Gun pair export/import for account backup
|
|
147
|
+
- Responsive modal design
|
|
148
|
+
- Error handling and user feedback
|
|
107
149
|
|
|
108
150
|
### useShogun Hook
|
|
109
151
|
|
|
110
|
-
A hook to access Shogun authentication state and functions.
|
|
152
|
+
A comprehensive hook to access Shogun authentication state and functions.
|
|
111
153
|
|
|
112
154
|
```tsx
|
|
113
155
|
import React, { useEffect } from "react";
|
|
114
156
|
import { useShogun } from "shogun-button-react";
|
|
115
157
|
|
|
116
|
-
function
|
|
158
|
+
function UserProfile() {
|
|
117
159
|
const {
|
|
160
|
+
// Authentication state
|
|
118
161
|
isLoggedIn,
|
|
119
162
|
userPub,
|
|
120
163
|
username,
|
|
164
|
+
|
|
165
|
+
// Authentication methods
|
|
121
166
|
login,
|
|
122
|
-
|
|
167
|
+
signUp,
|
|
123
168
|
logout,
|
|
169
|
+
|
|
170
|
+
// Plugin management
|
|
124
171
|
hasPlugin,
|
|
125
172
|
getPlugin,
|
|
173
|
+
|
|
174
|
+
// Account management
|
|
126
175
|
exportGunPair,
|
|
127
176
|
importGunPair,
|
|
177
|
+
|
|
178
|
+
// Data operations
|
|
128
179
|
observe,
|
|
180
|
+
put,
|
|
181
|
+
get,
|
|
182
|
+
remove,
|
|
183
|
+
|
|
184
|
+
// Advanced Gun hooks
|
|
185
|
+
useGunState,
|
|
186
|
+
useGunCollection,
|
|
187
|
+
useGunConnection,
|
|
188
|
+
useGunDebug,
|
|
189
|
+
useGunRealtime,
|
|
129
190
|
} = useShogun();
|
|
130
191
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// Or login with Nostr
|
|
142
|
-
await login("nostr");
|
|
143
|
-
|
|
144
|
-
// Or login with OAuth
|
|
145
|
-
await login("oauth", "google");
|
|
146
|
-
|
|
147
|
-
// Or login with Gun pair (for account recovery)
|
|
148
|
-
const pairData = {
|
|
149
|
-
/* Gun pair object */
|
|
150
|
-
};
|
|
151
|
-
await login("pair", pairData);
|
|
192
|
+
// Example: Login with different methods
|
|
193
|
+
const handlePasswordLogin = async () => {
|
|
194
|
+
try {
|
|
195
|
+
const result = await login("password", "username", "password");
|
|
196
|
+
if (result.success) {
|
|
197
|
+
console.log("Password login successful!");
|
|
198
|
+
}
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.error("Login failed:", error);
|
|
201
|
+
}
|
|
152
202
|
};
|
|
153
203
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
204
|
+
const handleMetaMaskLogin = async () => {
|
|
205
|
+
try {
|
|
206
|
+
const result = await login("web3");
|
|
207
|
+
if (result.success) {
|
|
208
|
+
console.log("MetaMask login successful!");
|
|
209
|
+
}
|
|
210
|
+
} catch (error) {
|
|
211
|
+
console.error("MetaMask login failed:", error);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
157
214
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
215
|
+
const handleWebAuthnLogin = async () => {
|
|
216
|
+
try {
|
|
217
|
+
const result = await login("webauthn", "username");
|
|
218
|
+
if (result.success) {
|
|
219
|
+
console.log("WebAuthn login successful!");
|
|
220
|
+
}
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error("WebAuthn login failed:", error);
|
|
223
|
+
}
|
|
161
224
|
};
|
|
162
225
|
|
|
163
|
-
|
|
226
|
+
// Example: Account backup and recovery
|
|
227
|
+
const handleExportAccount = async () => {
|
|
164
228
|
try {
|
|
165
|
-
const pairData = await exportGunPair("
|
|
166
|
-
console.log("
|
|
167
|
-
|
|
229
|
+
const pairData = await exportGunPair("my-secure-password");
|
|
230
|
+
console.log("Account exported successfully!");
|
|
231
|
+
|
|
232
|
+
// Save to file or copy to clipboard
|
|
233
|
+
if (navigator.clipboard) {
|
|
234
|
+
await navigator.clipboard.writeText(pairData);
|
|
235
|
+
alert("Account data copied to clipboard!");
|
|
236
|
+
}
|
|
168
237
|
} catch (error) {
|
|
169
238
|
console.error("Export failed:", error);
|
|
170
239
|
}
|
|
171
240
|
};
|
|
172
241
|
|
|
173
|
-
const
|
|
242
|
+
const handleImportAccount = async (pairData: string, password?: string) => {
|
|
174
243
|
try {
|
|
175
|
-
const success = await importGunPair(
|
|
244
|
+
const success = await importGunPair(pairData, password);
|
|
176
245
|
if (success) {
|
|
177
|
-
console.log("
|
|
246
|
+
console.log("Account imported successfully!");
|
|
178
247
|
}
|
|
179
248
|
} catch (error) {
|
|
180
249
|
console.error("Import failed:", error);
|
|
181
250
|
}
|
|
182
251
|
};
|
|
183
252
|
|
|
184
|
-
//
|
|
253
|
+
// Example: Real-time data observation
|
|
185
254
|
useEffect(() => {
|
|
186
255
|
if (isLoggedIn) {
|
|
187
|
-
const subscription = observe<any>(
|
|
188
|
-
console.log(
|
|
256
|
+
const subscription = observe<any>('user/profile').subscribe(data => {
|
|
257
|
+
console.log('Profile updated:', data);
|
|
189
258
|
});
|
|
190
|
-
|
|
259
|
+
|
|
191
260
|
return () => subscription.unsubscribe();
|
|
192
261
|
}
|
|
193
262
|
}, [isLoggedIn, observe]);
|
|
194
263
|
|
|
195
|
-
|
|
196
|
-
<div>
|
|
264
|
+
if (!isLoggedIn) {
|
|
265
|
+
return <div>Please log in to view your profile</div>;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return (
|
|
269
|
+
<div className="user-profile">
|
|
197
270
|
<h2>Welcome, {username}!</h2>
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
271
|
+
<div className="profile-info">
|
|
272
|
+
<p><strong>Public Key:</strong> {userPub}</p>
|
|
273
|
+
<p><strong>Authentication Method:</strong> {authMethod}</p>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
<div className="actions">
|
|
277
|
+
<button onClick={handleExportAccount}>Export Account</button>
|
|
278
|
+
<button onClick={logout}>Logout</button>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## 🔌 Advanced Gun Plugin Usage
|
|
286
|
+
|
|
287
|
+
### Using Gun State Hooks
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
function UserSettings() {
|
|
291
|
+
const { useGunState, useGunCollection } = useShogun();
|
|
292
|
+
|
|
293
|
+
// Single value state
|
|
294
|
+
const profile = useGunState('user/profile', {
|
|
295
|
+
name: '',
|
|
296
|
+
email: '',
|
|
297
|
+
preferences: {}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Collection management
|
|
301
|
+
const posts = useGunCollection('user/posts', {
|
|
302
|
+
pageSize: 10,
|
|
303
|
+
sortBy: 'createdAt',
|
|
304
|
+
sortOrder: 'desc',
|
|
305
|
+
filter: (post) => post.isPublished
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const updateProfile = async () => {
|
|
309
|
+
await profile.update({
|
|
310
|
+
name: 'New Name',
|
|
311
|
+
preferences: { theme: 'dark' }
|
|
312
|
+
});
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const addPost = async () => {
|
|
316
|
+
await posts.addItem({
|
|
317
|
+
title: 'New Post',
|
|
318
|
+
content: 'Post content...',
|
|
319
|
+
createdAt: Date.now(),
|
|
320
|
+
isPublished: true
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<div>
|
|
326
|
+
<h3>Profile Settings</h3>
|
|
327
|
+
{profile.isLoading ? (
|
|
328
|
+
<p>Loading...</p>
|
|
329
|
+
) : profile.error ? (
|
|
330
|
+
<p>Error: {profile.error}</p>
|
|
331
|
+
) : (
|
|
332
|
+
<div>
|
|
333
|
+
<input
|
|
334
|
+
value={profile.data?.name || ''}
|
|
335
|
+
onChange={(e) => profile.update({ name: e.target.value })}
|
|
336
|
+
placeholder="Name"
|
|
337
|
+
/>
|
|
338
|
+
<button onClick={updateProfile}>Save Changes</button>
|
|
339
|
+
</div>
|
|
340
|
+
)}
|
|
341
|
+
|
|
342
|
+
<h3>Your Posts ({posts.items.length})</h3>
|
|
343
|
+
{posts.isLoading ? (
|
|
344
|
+
<p>Loading posts...</p>
|
|
345
|
+
) : (
|
|
346
|
+
<div>
|
|
347
|
+
{posts.items.map((post, index) => (
|
|
348
|
+
<div key={index}>
|
|
349
|
+
<h4>{post.title}</h4>
|
|
350
|
+
<p>{post.content}</p>
|
|
351
|
+
</div>
|
|
352
|
+
))}
|
|
353
|
+
|
|
354
|
+
<div className="pagination">
|
|
355
|
+
{posts.hasPrevPage && (
|
|
356
|
+
<button onClick={posts.prevPage}>Previous</button>
|
|
357
|
+
)}
|
|
358
|
+
<span>Page {posts.currentPage + 1} of {posts.totalPages}</span>
|
|
359
|
+
{posts.hasNextPage && (
|
|
360
|
+
<button onClick={posts.nextPage}>Next</button>
|
|
361
|
+
)}
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
)}
|
|
365
|
+
</div>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Connection Monitoring
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
function ConnectionStatus() {
|
|
374
|
+
const { useGunConnection, useGunDebug } = useShogun();
|
|
375
|
+
|
|
376
|
+
// Monitor connection status
|
|
377
|
+
const connection = useGunConnection('user/data');
|
|
378
|
+
|
|
379
|
+
// Enable debug logging
|
|
380
|
+
useGunDebug('user/data', true);
|
|
381
|
+
|
|
382
|
+
return (
|
|
383
|
+
<div className="connection-status">
|
|
384
|
+
<div className={`status-indicator ${connection.isConnected ? 'connected' : 'disconnected'}`}>
|
|
385
|
+
{connection.isConnected ? '🟢 Connected' : '🔴 Disconnected'}
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
{connection.lastSeen && (
|
|
389
|
+
<p>Last seen: {connection.lastSeen.toLocaleTimeString()}</p>
|
|
390
|
+
)}
|
|
391
|
+
|
|
392
|
+
{connection.error && (
|
|
393
|
+
<p className="error">Error: {connection.error}</p>
|
|
394
|
+
)}
|
|
201
395
|
</div>
|
|
202
|
-
) : (
|
|
203
|
-
<div>Please login to continue</div>
|
|
204
396
|
);
|
|
205
397
|
}
|
|
206
398
|
```
|
|
207
399
|
|
|
208
|
-
##
|
|
400
|
+
## 🎨 Customization
|
|
401
|
+
|
|
402
|
+
### CSS Variables
|
|
403
|
+
|
|
404
|
+
Customize the appearance using CSS variables:
|
|
405
|
+
|
|
406
|
+
```css
|
|
407
|
+
:root {
|
|
408
|
+
/* Primary colors */
|
|
409
|
+
--shogun-primary: #3b82f6;
|
|
410
|
+
--shogun-primary-hover: #2563eb;
|
|
411
|
+
|
|
412
|
+
/* Background colors */
|
|
413
|
+
--shogun-bg: #ffffff;
|
|
414
|
+
--shogun-bg-secondary: #f3f4f6;
|
|
415
|
+
|
|
416
|
+
/* Text colors */
|
|
417
|
+
--shogun-text: #1f2937;
|
|
418
|
+
--shogun-text-secondary: #6b7280;
|
|
419
|
+
|
|
420
|
+
/* Border and shadow */
|
|
421
|
+
--shogun-border: #e5e7eb;
|
|
422
|
+
--shogun-border-radius: 12px;
|
|
423
|
+
--shogun-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
424
|
+
|
|
425
|
+
/* Transitions */
|
|
426
|
+
--shogun-transition: all 0.2s ease;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/* Dark mode overrides */
|
|
430
|
+
@media (prefers-color-scheme: dark) {
|
|
431
|
+
:root {
|
|
432
|
+
--shogun-bg: #1f2937;
|
|
433
|
+
--shogun-bg-secondary: #374151;
|
|
434
|
+
--shogun-text: #f3f4f6;
|
|
435
|
+
--shogun-text-secondary: #9ca3af;
|
|
436
|
+
--shogun-border: #4b5563;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Custom Styling
|
|
442
|
+
|
|
443
|
+
```css
|
|
444
|
+
/* Custom button styles */
|
|
445
|
+
.shogun-connect-button {
|
|
446
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
447
|
+
border-radius: 25px;
|
|
448
|
+
font-weight: 700;
|
|
449
|
+
text-transform: uppercase;
|
|
450
|
+
letter-spacing: 1px;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* Custom modal styles */
|
|
454
|
+
.shogun-modal {
|
|
455
|
+
border-radius: 20px;
|
|
456
|
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* Custom form styles */
|
|
460
|
+
.shogun-form-group input {
|
|
461
|
+
border-radius: 10px;
|
|
462
|
+
border: 2px solid transparent;
|
|
463
|
+
transition: border-color 0.3s ease;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
.shogun-form-group input:focus {
|
|
467
|
+
border-color: var(--shogun-primary);
|
|
468
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
## 🔧 Configuration Options
|
|
209
473
|
|
|
210
|
-
|
|
474
|
+
### Complete Configuration Interface
|
|
211
475
|
|
|
212
476
|
```typescript
|
|
213
477
|
interface ShogunConnectorOptions {
|
|
214
478
|
// App information
|
|
215
479
|
appName: string;
|
|
216
|
-
appDescription?: string;
|
|
217
|
-
appUrl?: string;
|
|
218
|
-
appIcon?: string;
|
|
219
480
|
|
|
220
481
|
// Feature toggles
|
|
221
482
|
showMetamask?: boolean;
|
|
@@ -225,165 +486,102 @@ interface ShogunConnectorOptions {
|
|
|
225
486
|
darkMode?: boolean;
|
|
226
487
|
|
|
227
488
|
// Network configuration
|
|
228
|
-
websocketSecure?: boolean;
|
|
229
|
-
providerUrl?: string | null;
|
|
230
489
|
peers?: string[];
|
|
231
490
|
authToken?: string;
|
|
232
491
|
gunInstance?: IGunInstance<any>;
|
|
233
492
|
|
|
234
|
-
//
|
|
493
|
+
// Timeouts and provider configs
|
|
235
494
|
timeouts?: {
|
|
236
495
|
login?: number;
|
|
237
496
|
signup?: number;
|
|
238
497
|
operation?: number;
|
|
239
498
|
};
|
|
240
499
|
oauth?: {
|
|
241
|
-
providers: Record<
|
|
242
|
-
string
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
redirectUri?: string;
|
|
247
|
-
}
|
|
248
|
-
>;
|
|
500
|
+
providers: Record<string, {
|
|
501
|
+
clientId: string;
|
|
502
|
+
redirectUri?: string;
|
|
503
|
+
clientSecret?: string;
|
|
504
|
+
}>;
|
|
249
505
|
};
|
|
506
|
+
|
|
507
|
+
// Gun Advanced Plugin configuration
|
|
508
|
+
enableGunDebug?: boolean;
|
|
509
|
+
enableConnectionMonitoring?: boolean;
|
|
510
|
+
defaultPageSize?: number;
|
|
511
|
+
connectionTimeout?: number;
|
|
512
|
+
debounceInterval?: number;
|
|
250
513
|
}
|
|
251
514
|
```
|
|
252
515
|
|
|
253
|
-
|
|
516
|
+
### Connector Result
|
|
254
517
|
|
|
255
518
|
```typescript
|
|
256
519
|
interface ShogunConnectorResult {
|
|
257
|
-
|
|
520
|
+
core: ShogunCore;
|
|
258
521
|
options: ShogunConnectorOptions;
|
|
522
|
+
setProvider: (provider: any) => boolean;
|
|
523
|
+
getCurrentProviderUrl: () => string | null;
|
|
259
524
|
registerPlugin: (plugin: any) => boolean;
|
|
260
525
|
hasPlugin: (name: string) => boolean;
|
|
526
|
+
gunPlugin: GunAdvancedPlugin;
|
|
261
527
|
}
|
|
262
528
|
```
|
|
263
529
|
|
|
264
|
-
##
|
|
265
|
-
|
|
266
|
-
### Password Authentication
|
|
267
|
-
|
|
268
|
-
```tsx
|
|
269
|
-
// Login
|
|
270
|
-
await login("password", "username", "password");
|
|
271
|
-
|
|
272
|
-
// Sign up
|
|
273
|
-
await signup("password", "username", "password");
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Web3 Authentication (MetaMask)
|
|
277
|
-
|
|
278
|
-
```tsx
|
|
279
|
-
// Login with MetaMask
|
|
280
|
-
await login("web3");
|
|
281
|
-
|
|
282
|
-
// Sign up with MetaMask
|
|
283
|
-
await signup("web3");
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### WebAuthn Authentication
|
|
287
|
-
|
|
288
|
-
```tsx
|
|
289
|
-
// Login with WebAuthn
|
|
290
|
-
await login("webauthn", "username");
|
|
291
|
-
|
|
292
|
-
// Sign up with WebAuthn
|
|
293
|
-
await signup("webauthn", "username");
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
### Nostr Authentication
|
|
297
|
-
|
|
298
|
-
```tsx
|
|
299
|
-
// Login with Nostr
|
|
300
|
-
await login("nostr");
|
|
301
|
-
|
|
302
|
-
// Sign up with Nostr
|
|
303
|
-
await signup("nostr");
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
### OAuth Authentication
|
|
530
|
+
## 🌐 Browser Support
|
|
307
531
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
532
|
+
- **Chrome** ≥ 60
|
|
533
|
+
- **Firefox** ≥ 60
|
|
534
|
+
- **Safari** ≥ 12
|
|
535
|
+
- **Edge** ≥ 79
|
|
311
536
|
|
|
312
|
-
|
|
313
|
-
await signup("oauth", "google");
|
|
314
|
-
```
|
|
537
|
+
## 📱 Mobile Support
|
|
315
538
|
|
|
316
|
-
|
|
539
|
+
The library is fully responsive and works seamlessly on mobile devices. All authentication methods are optimized for touch interfaces.
|
|
317
540
|
|
|
318
|
-
|
|
319
|
-
// Login with exported pair
|
|
320
|
-
await login("pair", pairData);
|
|
541
|
+
## 🔒 Security Features
|
|
321
542
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
543
|
+
- **Encrypted Storage**: Gun pairs can be encrypted with passwords
|
|
544
|
+
- **Secure Authentication**: Multiple secure authentication methods
|
|
545
|
+
- **Session Management**: Automatic session handling and cleanup
|
|
546
|
+
- **Error Handling**: Comprehensive error handling and user feedback
|
|
325
547
|
|
|
326
|
-
##
|
|
548
|
+
## 🚀 Performance
|
|
327
549
|
|
|
328
|
-
|
|
329
|
-
|
|
550
|
+
- **Lazy Loading**: Components load only when needed
|
|
551
|
+
- **Optimized Rendering**: Efficient React rendering with proper memoization
|
|
552
|
+
- **Connection Pooling**: Smart connection management for optimal performance
|
|
553
|
+
- **Debounced Updates**: Prevents excessive re-renders during rapid data changes
|
|
330
554
|
|
|
331
|
-
|
|
332
|
-
if (hasPlugin("web3")) {
|
|
333
|
-
const web3Plugin = getPlugin("web3");
|
|
334
|
-
// Use the plugin
|
|
335
|
-
}
|
|
555
|
+
## 🤝 Contributing
|
|
336
556
|
|
|
337
|
-
|
|
338
|
-
```
|
|
557
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
339
558
|
|
|
340
|
-
|
|
559
|
+
### Development Setup
|
|
341
560
|
|
|
342
|
-
|
|
561
|
+
```bash
|
|
562
|
+
# Clone the repository
|
|
563
|
+
git clone https://github.com/shogun/shogun-button-react.git
|
|
343
564
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
--shogun-button-primary: #5c6bc0;
|
|
347
|
-
--shogun-button-hover: #3f51b5;
|
|
348
|
-
--shogun-text-primary: #333333;
|
|
349
|
-
--shogun-background: #ffffff;
|
|
350
|
-
--shogun-border-radius: 8px;
|
|
351
|
-
--shogun-font-family:
|
|
352
|
-
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
353
|
-
--shogun-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
354
|
-
--shogun-transition: all 0.2s ease-in-out;
|
|
355
|
-
}
|
|
356
|
-
```
|
|
565
|
+
# Install dependencies
|
|
566
|
+
yarn install
|
|
357
567
|
|
|
358
|
-
|
|
568
|
+
# Start development server
|
|
569
|
+
yarn dev
|
|
359
570
|
|
|
360
|
-
|
|
571
|
+
# Build the library
|
|
572
|
+
yarn build
|
|
361
573
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
appName: "My App",
|
|
365
|
-
darkMode: true, // Enable dark mode
|
|
366
|
-
});
|
|
574
|
+
# Run tests
|
|
575
|
+
yarn test
|
|
367
576
|
```
|
|
368
577
|
|
|
369
|
-
##
|
|
370
|
-
|
|
371
|
-
- Chrome ≥ 60
|
|
372
|
-
- Firefox ≥ 60
|
|
373
|
-
- Safari ≥ 12
|
|
374
|
-
- Edge ≥ 79
|
|
375
|
-
|
|
376
|
-
## Dependencies
|
|
377
|
-
|
|
378
|
-
- React ≥ 18.0.0
|
|
379
|
-
- shogun-core ≥ 1.5.19
|
|
380
|
-
- ethers ≥ 6.13.5
|
|
381
|
-
- rxjs ≥ 7.8.1
|
|
578
|
+
## 📄 License
|
|
382
579
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
580
|
+
MIT © [Shogun](https://github.com/shogun)
|
|
386
581
|
|
|
387
|
-
##
|
|
582
|
+
## 🆘 Support
|
|
388
583
|
|
|
389
|
-
|
|
584
|
+
- **Documentation**: [Full API Reference](https://docs.shogun.dev)
|
|
585
|
+
- **Issues**: [GitHub Issues](https://github.com/shogun/shogun-button-react/issues)
|
|
586
|
+
- **Discussions**: [GitHub Discussions](https://github.com/shogun/shogun-button-react/discussions)
|
|
587
|
+
- **Discord**: [Join our community](https://discord.gg/shogun)
|