@rqdhw3n/react-auth-flow 1.0.3 → 1.0.5
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 +261 -569
- package/dist/index.cjs.js +486 -239
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +32 -7
- package/dist/index.es.js +486 -239
- package/dist/index.es.js.map +1 -1
- package/dist/style.css +253 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -1,569 +1,261 @@
|
|
|
1
|
-
# @rqdhw3n/react-auth-flow
|
|
2
|
-
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
## Features
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const user = await login({
|
|
263
|
-
email: 'user@example.com',
|
|
264
|
-
password: 'password',
|
|
265
|
-
rememberMe: true,
|
|
266
|
-
});
|
|
267
|
-
console.log('Logged in as:', user);
|
|
268
|
-
} catch (err) {
|
|
269
|
-
console.error('Login failed:', err);
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
const handleLogout = async () => {
|
|
274
|
-
await logout();
|
|
275
|
-
console.log('Logged out');
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
if (isLoading) {
|
|
279
|
-
return <div>Loading...</div>;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (error) {
|
|
283
|
-
return <div>Error: {error.message}</div>;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (!isAuthenticated) {
|
|
287
|
-
return <button onClick={handleLogin}>Login</button>;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return (
|
|
291
|
-
<div>
|
|
292
|
-
<h1>Hello, {user?.name}</h1>
|
|
293
|
-
<p>Email: {user?.email}</p>
|
|
294
|
-
<p>Roles: {user?.roles?.join(', ')}</p>
|
|
295
|
-
<button onClick={handleLogout}>Logout</button>
|
|
296
|
-
<button onClick={refreshSession}>Refresh Session</button>
|
|
297
|
-
</div>
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
## API Endpoints Configuration
|
|
303
|
-
|
|
304
|
-
The package expects your backend to provide the following endpoints by default:
|
|
305
|
-
|
|
306
|
-
### Default Endpoints
|
|
307
|
-
|
|
308
|
-
- `POST /auth/login` - Login with email and password
|
|
309
|
-
- `POST /auth/register` - Register a new account
|
|
310
|
-
- `POST /auth/logout` - Logout the user
|
|
311
|
-
- `GET /auth/me` - Get current user information
|
|
312
|
-
- `POST /auth/refresh` - Refresh authentication token
|
|
313
|
-
- `POST /auth/forgot-password` - Request password reset
|
|
314
|
-
- `POST /auth/reset-password` - Reset password with token
|
|
315
|
-
- `POST /auth/verify-email` - Verify email with token
|
|
316
|
-
|
|
317
|
-
### Customizing Endpoints
|
|
318
|
-
|
|
319
|
-
```tsx
|
|
320
|
-
import { AuthProvider } from '@rqdhw3n/react-auth-flow';
|
|
321
|
-
|
|
322
|
-
<AuthProvider
|
|
323
|
-
baseURL="https://api.example.com"
|
|
324
|
-
endpoints={{
|
|
325
|
-
login: '/auth/signin',
|
|
326
|
-
register: '/auth/signup',
|
|
327
|
-
me: '/user/profile',
|
|
328
|
-
// ... other endpoints
|
|
329
|
-
}}
|
|
330
|
-
>
|
|
331
|
-
{/* Your app */}
|
|
332
|
-
</AuthProvider>
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
## Expected API Response Formats
|
|
336
|
-
|
|
337
|
-
### Login Response
|
|
338
|
-
|
|
339
|
-
```json
|
|
340
|
-
{
|
|
341
|
-
"user": {
|
|
342
|
-
"id": 1,
|
|
343
|
-
"name": "John Doe",
|
|
344
|
-
"email": "john@example.com",
|
|
345
|
-
"roles": ["admin"],
|
|
346
|
-
"permissions": ["users.manage", "users.delete"]
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Current User (Me) Response
|
|
352
|
-
|
|
353
|
-
```json
|
|
354
|
-
{
|
|
355
|
-
"user": {
|
|
356
|
-
"id": 1,
|
|
357
|
-
"name": "John Doe",
|
|
358
|
-
"email": "john@example.com",
|
|
359
|
-
"roles": ["admin"],
|
|
360
|
-
"permissions": ["users.manage", "users.delete"]
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
### Error Response
|
|
366
|
-
|
|
367
|
-
```json
|
|
368
|
-
{
|
|
369
|
-
"error": {
|
|
370
|
-
"code": "INVALID_CREDENTIALS",
|
|
371
|
-
"message": "Invalid email or password",
|
|
372
|
-
"statusCode": 401
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
## HttpOnly Cookie JWT Authentication
|
|
378
|
-
|
|
379
|
-
For enhanced security, configure your backend to use HttpOnly cookies:
|
|
380
|
-
|
|
381
|
-
```tsx
|
|
382
|
-
// Backend should set a cookie like:
|
|
383
|
-
// Set-Cookie: jwt=token; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
|
|
384
|
-
|
|
385
|
-
// The package will automatically include cookies with requests
|
|
386
|
-
// because credentials: "include" is set by default
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
## Custom Headers and Request Adapter
|
|
390
|
-
|
|
391
|
-
```tsx
|
|
392
|
-
import { createAuthClient } from '@rqdhw3n/react-auth-flow';
|
|
393
|
-
|
|
394
|
-
// Create a custom client
|
|
395
|
-
const authClient = createAuthClient({
|
|
396
|
-
baseURL: 'https://api.example.com',
|
|
397
|
-
headers: {
|
|
398
|
-
'X-API-Key': 'your-api-key',
|
|
399
|
-
'X-Client-Version': '1.0.0',
|
|
400
|
-
},
|
|
401
|
-
credentials: 'include', // for HttpOnly cookies
|
|
402
|
-
adapter: async (url, options) => {
|
|
403
|
-
// Custom request logic
|
|
404
|
-
console.log('Making request to:', url);
|
|
405
|
-
return fetch(url, options);
|
|
406
|
-
},
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
// Use in AuthProvider
|
|
410
|
-
<AuthProvider
|
|
411
|
-
baseURL="https://api.example.com"
|
|
412
|
-
// ... other config
|
|
413
|
-
>
|
|
414
|
-
{/* Your app */}
|
|
415
|
-
</AuthProvider>
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
## TypeScript Customization
|
|
419
|
-
|
|
420
|
-
Extend types for your application:
|
|
421
|
-
|
|
422
|
-
```tsx
|
|
423
|
-
import { AuthUser, AuthContextValue } from '@rqdhw3n/react-auth-flow';
|
|
424
|
-
|
|
425
|
-
// Extend the AuthUser type
|
|
426
|
-
interface AppUser extends AuthUser {
|
|
427
|
-
id: number;
|
|
428
|
-
name: string;
|
|
429
|
-
email: string;
|
|
430
|
-
roles: string[];
|
|
431
|
-
permissions: string[];
|
|
432
|
-
company?: string;
|
|
433
|
-
department?: string;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// Use in your components
|
|
437
|
-
import { useAuth } from '@rqdhw3n/react-auth-flow';
|
|
438
|
-
|
|
439
|
-
function MyComponent() {
|
|
440
|
-
const { user } = useAuth();
|
|
441
|
-
const appUser = user as AppUser;
|
|
442
|
-
|
|
443
|
-
return <div>Working in {appUser.department}</div>;
|
|
444
|
-
}
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
## Styling Components
|
|
448
|
-
|
|
449
|
-
All form components use semantic class names for styling:
|
|
450
|
-
|
|
451
|
-
```css
|
|
452
|
-
.auth-form-group {
|
|
453
|
-
margin-bottom: 1rem;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
.auth-form-label {
|
|
457
|
-
display: block;
|
|
458
|
-
margin-bottom: 0.5rem;
|
|
459
|
-
font-weight: 500;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
.auth-form-input {
|
|
463
|
-
width: 100%;
|
|
464
|
-
padding: 0.5rem;
|
|
465
|
-
border: 1px solid #ccc;
|
|
466
|
-
border-radius: 4px;
|
|
467
|
-
font-size: 1rem;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
.auth-form-input:disabled {
|
|
471
|
-
background-color: #f5f5f5;
|
|
472
|
-
cursor: not-allowed;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
.auth-form-error {
|
|
476
|
-
color: #dc3545;
|
|
477
|
-
margin-top: 0.5rem;
|
|
478
|
-
font-size: 0.875rem;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
.auth-form-button {
|
|
482
|
-
padding: 0.5rem 1rem;
|
|
483
|
-
border: none;
|
|
484
|
-
border-radius: 4px;
|
|
485
|
-
font-size: 1rem;
|
|
486
|
-
cursor: pointer;
|
|
487
|
-
width: 100%;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
.auth-form-button-primary {
|
|
491
|
-
background-color: #007bff;
|
|
492
|
-
color: white;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
.auth-form-button-primary:hover {
|
|
496
|
-
background-color: #0056b3;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
.auth-form-button:disabled {
|
|
500
|
-
opacity: 0.5;
|
|
501
|
-
cursor: not-allowed;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
.auth-form-checkbox {
|
|
505
|
-
display: flex;
|
|
506
|
-
align-items: center;
|
|
507
|
-
gap: 0.5rem;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
.auth-form-checkbox .auth-form-label {
|
|
511
|
-
margin-bottom: 0;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
.auth-form-success {
|
|
515
|
-
padding: 1rem;
|
|
516
|
-
background-color: #d4edda;
|
|
517
|
-
border: 1px solid #c3e6cb;
|
|
518
|
-
border-radius: 4px;
|
|
519
|
-
color: #155724;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
.auth-form-success-message {
|
|
523
|
-
margin: 0;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
.auth-loading {
|
|
527
|
-
text-align: center;
|
|
528
|
-
padding: 2rem;
|
|
529
|
-
font-size: 1rem;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
.auth-forbidden {
|
|
533
|
-
padding: 2rem;
|
|
534
|
-
text-align: center;
|
|
535
|
-
color: #dc3545;
|
|
536
|
-
}
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
## Error Handling
|
|
540
|
-
|
|
541
|
-
The package normalizes all errors to a consistent format:
|
|
542
|
-
|
|
543
|
-
```tsx
|
|
544
|
-
import { useAuth, AuthError } from '@rqdhw3n/react-auth-flow';
|
|
545
|
-
|
|
546
|
-
function MyComponent() {
|
|
547
|
-
const { error } = useAuth();
|
|
548
|
-
|
|
549
|
-
if (error) {
|
|
550
|
-
const authError: AuthError = error;
|
|
551
|
-
console.log({
|
|
552
|
-
code: authError.code, // e.g., "INVALID_CREDENTIALS"
|
|
553
|
-
message: authError.message,
|
|
554
|
-
statusCode: authError.statusCode, // e.g., 401
|
|
555
|
-
details: authError.details, // additional error info
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
return <div>Status: {error?.message}</div>;
|
|
560
|
-
}
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
## License
|
|
564
|
-
|
|
565
|
-
MIT
|
|
566
|
-
|
|
567
|
-
## Support
|
|
568
|
-
|
|
569
|
-
For issues and feature requests, please visit the [GitHub repository](https://github.com/rqdhw3n/react-auth-flow).
|
|
1
|
+
# @rqdhw3n/react-auth-flow
|
|
2
|
+
|
|
3
|
+
A TypeScript-first authentication flow package for React applications with built-in, production-ready auth form styling.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Secure by default with cookie-based auth support
|
|
8
|
+
- Zero UI framework dependency
|
|
9
|
+
- Built-in stylesheet loaded automatically from the package entry
|
|
10
|
+
- Ready-to-use `LoginForm`, `RegisterForm`, `ForgotPasswordForm`, `ResetPasswordForm`, and `VerifyEmailForm`
|
|
11
|
+
- `AuthProvider` and `useAuth()` for auth state management
|
|
12
|
+
- `ProtectedRoute` support for React Router
|
|
13
|
+
- Customizable endpoints, headers, and request adapters
|
|
14
|
+
- Override-friendly class name props for consumer styling
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @rqdhw3n/react-auth-flow react react-dom react-router-dom
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
No Tailwind, PostCSS, `tailwind.config.js`, or manual CSS import is required. Importing the package automatically loads the packaged auth stylesheet.
|
|
23
|
+
|
|
24
|
+
## Quick Setup
|
|
25
|
+
|
|
26
|
+
### Wrap your app with `AuthProvider`
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { AuthProvider } from "@rqdhw3n/react-auth-flow";
|
|
30
|
+
|
|
31
|
+
function App() {
|
|
32
|
+
return (
|
|
33
|
+
<AuthProvider
|
|
34
|
+
baseURL="https://api.example.com"
|
|
35
|
+
autoRefresh={true}
|
|
36
|
+
refreshInterval={5 * 60 * 1000}
|
|
37
|
+
>
|
|
38
|
+
{/* your app */}
|
|
39
|
+
</AuthProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Use `useAuth()`
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { useAuth } from "@rqdhw3n/react-auth-flow";
|
|
48
|
+
|
|
49
|
+
function Header() {
|
|
50
|
+
const { user, isAuthenticated, logout } = useAuth();
|
|
51
|
+
|
|
52
|
+
if (!isAuthenticated) {
|
|
53
|
+
return <span>Please log in</span>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div>
|
|
58
|
+
<p>Welcome, {user?.name}</p>
|
|
59
|
+
<button onClick={logout}>Logout</button>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Forms
|
|
66
|
+
|
|
67
|
+
### Styled out of the box
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { LoginForm } from "@rqdhw3n/react-auth-flow";
|
|
71
|
+
|
|
72
|
+
function App() {
|
|
73
|
+
return <LoginForm />;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Login form
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import { LoginForm } from "@rqdhw3n/react-auth-flow";
|
|
81
|
+
import { useNavigate } from "react-router-dom";
|
|
82
|
+
|
|
83
|
+
function LoginPage() {
|
|
84
|
+
const navigate = useNavigate();
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
style={{
|
|
89
|
+
minHeight: "100vh",
|
|
90
|
+
display: "grid",
|
|
91
|
+
placeItems: "center",
|
|
92
|
+
padding: 24,
|
|
93
|
+
background: "#f4f7fb",
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<LoginForm
|
|
97
|
+
title="Welcome back"
|
|
98
|
+
subtitle="Sign in to continue"
|
|
99
|
+
submitButtonText="Sign In"
|
|
100
|
+
loadingText="Signing in..."
|
|
101
|
+
labels={{
|
|
102
|
+
email: "Email Address",
|
|
103
|
+
password: "Password",
|
|
104
|
+
rememberMe: "Keep me signed in",
|
|
105
|
+
}}
|
|
106
|
+
onSuccess={() => navigate("/dashboard")}
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Register form
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
import { RegisterForm } from "@rqdhw3n/react-auth-flow";
|
|
117
|
+
|
|
118
|
+
function SignUpPage() {
|
|
119
|
+
return (
|
|
120
|
+
<RegisterForm
|
|
121
|
+
title="Create your account"
|
|
122
|
+
subtitle="Get started in seconds"
|
|
123
|
+
submitButtonText="Create Account"
|
|
124
|
+
loadingText="Creating account..."
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Forgot password form
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { ForgotPasswordForm } from "@rqdhw3n/react-auth-flow";
|
|
134
|
+
|
|
135
|
+
function ForgotPasswordPage() {
|
|
136
|
+
return (
|
|
137
|
+
<ForgotPasswordForm
|
|
138
|
+
title="Reset your password"
|
|
139
|
+
subtitle="Enter your email to receive a reset link"
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Reset password form
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import { ResetPasswordForm } from "@rqdhw3n/react-auth-flow";
|
|
149
|
+
import { useSearchParams } from "react-router-dom";
|
|
150
|
+
|
|
151
|
+
function ResetPasswordPage() {
|
|
152
|
+
const [searchParams] = useSearchParams();
|
|
153
|
+
const token = searchParams.get("token") || "";
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<ResetPasswordForm
|
|
157
|
+
token={token}
|
|
158
|
+
title="Create a new password"
|
|
159
|
+
subtitle="Use at least 8 characters"
|
|
160
|
+
/>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Verify email form
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
import { VerifyEmailForm } from "@rqdhw3n/react-auth-flow";
|
|
169
|
+
import { useSearchParams } from "react-router-dom";
|
|
170
|
+
|
|
171
|
+
function VerifyEmailPage() {
|
|
172
|
+
const [searchParams] = useSearchParams();
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<VerifyEmailForm
|
|
176
|
+
token={searchParams.get("token") || ""}
|
|
177
|
+
email={searchParams.get("email") || ""}
|
|
178
|
+
title="Verify your email"
|
|
179
|
+
subtitle="Enter the verification code you received"
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Styling Overrides
|
|
186
|
+
|
|
187
|
+
The package ships with default classes and also supports consumer overrides through props:
|
|
188
|
+
|
|
189
|
+
- `className`
|
|
190
|
+
- `formClassName`
|
|
191
|
+
- `fieldClassName`
|
|
192
|
+
- `labelClassName`
|
|
193
|
+
- `inputClassName`
|
|
194
|
+
- `buttonClassName`
|
|
195
|
+
- `errorClassName`
|
|
196
|
+
- `successClassName`
|
|
197
|
+
- `titleClassName`
|
|
198
|
+
- `subtitleClassName`
|
|
199
|
+
|
|
200
|
+
Example:
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import { LoginForm } from "@rqdhw3n/react-auth-flow";
|
|
204
|
+
|
|
205
|
+
function CustomLoginPage() {
|
|
206
|
+
return (
|
|
207
|
+
<LoginForm
|
|
208
|
+
className="my-auth-card"
|
|
209
|
+
formClassName="my-auth-form"
|
|
210
|
+
labelClassName="my-auth-label"
|
|
211
|
+
inputClassName="my-auth-input"
|
|
212
|
+
buttonClassName="my-auth-button"
|
|
213
|
+
errorClassName="my-auth-error"
|
|
214
|
+
successClassName="my-auth-success"
|
|
215
|
+
/>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Default packaged class names:
|
|
221
|
+
|
|
222
|
+
- `.rq-auth-container`
|
|
223
|
+
- `.rq-auth-form`
|
|
224
|
+
- `.rq-auth-field`
|
|
225
|
+
- `.rq-auth-label`
|
|
226
|
+
- `.rq-auth-input`
|
|
227
|
+
- `.rq-auth-button`
|
|
228
|
+
- `.rq-auth-error`
|
|
229
|
+
- `.rq-auth-success`
|
|
230
|
+
- `.rq-auth-title`
|
|
231
|
+
- `.rq-auth-subtitle`
|
|
232
|
+
- `.rq-auth-checkbox`
|
|
233
|
+
|
|
234
|
+
## Protected Routes
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
import { ProtectedRoute } from "@rqdhw3n/react-auth-flow";
|
|
238
|
+
import { Routes, Route } from "react-router-dom";
|
|
239
|
+
|
|
240
|
+
function AppRoutes() {
|
|
241
|
+
return (
|
|
242
|
+
<Routes>
|
|
243
|
+
<Route path="/login" element={<LoginPage />} />
|
|
244
|
+
<Route
|
|
245
|
+
path="/dashboard"
|
|
246
|
+
element={
|
|
247
|
+
<ProtectedRoute redirectTo="/login">
|
|
248
|
+
<Dashboard />
|
|
249
|
+
</ProtectedRoute>
|
|
250
|
+
}
|
|
251
|
+
/>
|
|
252
|
+
</Routes>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Notes
|
|
258
|
+
|
|
259
|
+
- The package stylesheet is imported from `src/index.ts`, so consumers do not need `import "./styles.css"` in their apps.
|
|
260
|
+
- Build output includes JavaScript bundles and an emitted CSS asset in `dist`.
|
|
261
|
+
- The components are responsive by default and work on desktop and mobile without extra setup.
|