@rqdhw3n/react-auth-flow 1.0.4 → 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 CHANGED
@@ -1,631 +1,261 @@
1
- # @rqdhw3n/react-auth-flow
2
-
3
- A production-ready, TypeScript-first authentication flow package for React applications. Provides a complete solution for handling user authentication with minimal configuration while maintaining flexibility.
4
-
5
- ## Features
6
-
7
- - 🔐 **Secure by default**: HttpOnly cookie JWT support
8
- - ⚡ **Zero dependencies**: Uses native fetch API
9
- - 🎣 **Custom hooks**: `useAuth()` hook for accessing auth state
10
- - 🔄 **Auto-refresh**: Automatic session refresh capability
11
- - 🎨 **Unstyled components**: Ready-to-use forms with full customization
12
- - 🛣️ **Protected routes**: React Router v6 compatible route protection
13
- - 📦 **TypeScript support**: Full type safety throughout
14
- - 🔌 **Customizable**: Custom headers, endpoints, and request adapters
15
- - 🚀 **SSR-friendly**: Works with server-side rendering when configured properly
16
-
17
- ## Installation
18
-
19
- ```bash
20
- npm install @rqdhw3n/react-auth-flow react react-dom react-router-dom
21
- ```
22
-
23
- or with yarn:
24
-
25
- ```bash
26
- yarn add @rqdhw3n/react-auth-flow react react-dom react-router-dom
27
- ```
28
-
29
- ## Quick Setup
30
-
31
- ### 1. Wrap your app with AuthProvider
32
-
33
- ```tsx
34
- import { AuthProvider } from '@rqdhw3n/react-auth-flow';
35
-
36
- function App() {
37
- return (
38
- <AuthProvider
39
- baseURL="https://api.example.com"
40
- autoRefresh={true}
41
- refreshInterval={5 * 60 * 1000} // 5 minutes
42
- >
43
- {/* Your app components */}
44
- </AuthProvider>
45
- );
46
- }
47
- ```
48
-
49
- ### 2. Use the useAuth hook
50
-
51
- ```tsx
52
- import { useAuth } from '@rqdhw3n/react-auth-flow';
53
-
54
- function Header() {
55
- const { user, isAuthenticated, logout } = useAuth();
56
-
57
- if (!isAuthenticated) {
58
- return <span>Please log in</span>;
59
- }
60
-
61
- return (
62
- <div>
63
- <p>Welcome, {user?.name}</p>
64
- <button onClick={logout}>Logout</button>
65
- </div>
66
- );
67
- }
68
- ```
69
-
70
- ## Usage Examples
71
-
72
- ### LoginForm Component with Tailwind CSS
73
-
74
- ```tsx
75
- import { LoginForm } from '@rqdhw3n/react-auth-flow';
76
- import { useNavigate } from 'react-router-dom';
77
-
78
- function LoginPage() {
79
- const navigate = useNavigate();
80
-
81
- return (
82
- <div className="flex min-h-screen items-center justify-center bg-slate-50 px-4 py-12">
83
- <LoginForm
84
- title="Welcome back"
85
- subtitle="Sign in to your account"
86
- className="w-full max-w-md rounded-2xl border border-slate-200 bg-white p-8 shadow-lg"
87
- formClassName="space-y-5"
88
- fieldClassName="space-y-2"
89
- labelClassName="block text-sm font-medium text-slate-700"
90
- inputClassName="w-full rounded-lg border border-slate-300 px-4 py-2 text-sm focus:border-blue-500 focus:ring-4 focus:ring-blue-100"
91
- buttonClassName="w-full rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700"
92
- submitButtonText="Sign In"
93
- loadingText="Signing in..."
94
- labels={{
95
- email: 'Email Address',
96
- password: 'Password',
97
- rememberMe: 'Keep me signed in',
98
- }}
99
- placeholders={{
100
- email: 'you@example.com',
101
- password: 'Enter your password',
102
- }}
103
- onSuccess={() => navigate('/dashboard')}
104
- onError={(error) => console.error(error.message)}
105
- />
106
- </div>
107
- );
108
- }
109
- ```
110
-
111
- ### RegisterForm Component with Tailwind CSS
112
-
113
- ```tsx
114
- import { RegisterForm } from '@rqdhw3n/react-auth-flow';
115
- import { useNavigate, Link } from 'react-router-dom';
116
-
117
- function SignUpPage() {
118
- const navigate = useNavigate();
119
-
120
- return (
121
- <div className="flex min-h-screen items-center justify-center bg-slate-50 px-4 py-12">
122
- <div className="w-full max-w-md">
123
- <RegisterForm
124
- title="Create your account"
125
- subtitle="Get started in seconds"
126
- className="rounded-2xl border border-slate-200 bg-white p-8 shadow-lg"
127
- formClassName="space-y-5"
128
- fieldClassName="space-y-2"
129
- labelClassName="block text-sm font-medium text-slate-700"
130
- inputClassName="w-full rounded-lg border border-slate-300 px-4 py-2 text-sm focus:border-blue-500 focus:ring-4 focus:ring-blue-100"
131
- buttonClassName="w-full rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700"
132
- submitButtonText="Create Account"
133
- loadingText="Creating..."
134
- labels={{
135
- name: 'Full Name',
136
- email: 'Email',
137
- password: 'Password',
138
- confirmPassword: 'Confirm Password',
139
- }}
140
- onSuccess={() => navigate('/email-verify')}
141
- />
142
- <p className="mt-4 text-center text-sm text-slate-600">
143
- Already have an account?{' '}
144
- <Link to="/login" className="font-semibold text-blue-600 hover:text-blue-700">
145
- Sign in
146
- </Link>
147
- </p>
148
- </div>
149
- </div>
150
- );
151
- }
152
- ```
153
-
154
- ### ForgotPasswordForm Component
155
-
156
- ```tsx
157
- import { ForgotPasswordForm } from '@rqdhw3n/react-auth-flow';
158
-
159
- function ForgotPasswordPage() {
160
- return (
161
- <div className="flex min-h-screen items-center justify-center bg-slate-50 px-4 py-12">
162
- <ForgotPasswordForm
163
- title="Reset your password"
164
- subtitle="Enter your email to receive a reset link"
165
- className="w-full max-w-md rounded-2xl border border-slate-200 bg-white p-8 shadow-lg"
166
- formClassName="space-y-5"
167
- fieldClassName="space-y-2"
168
- labelClassName="block text-sm font-medium text-slate-700"
169
- inputClassName="w-full rounded-lg border border-slate-300 px-4 py-2 text-sm focus:border-blue-500 focus:ring-4 focus:ring-blue-100"
170
- buttonClassName="w-full rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700"
171
- errorClassName="rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-600"
172
- successClassName="rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-700"
173
- submitButtonText="Send Reset Link"
174
- loadingText="Sending..."
175
- onSuccess={() => {
176
- alert('Check your email for reset link');
177
- }}
178
- />
179
- </div>
180
- );
181
- }
182
- ```
183
-
184
- ### ResetPasswordForm Component
185
-
186
- ```tsx
187
- import { ResetPasswordForm } from '@rqdhw3n/react-auth-flow';
188
- import { useSearchParams, useNavigate } from 'react-router-dom';
189
-
190
- function ResetPasswordPage() {
191
- const [searchParams] = useSearchParams();
192
- const navigate = useNavigate();
193
- const token = searchParams.get('token') || '';
194
-
195
- return (
196
- <div className="flex min-h-screen items-center justify-center bg-slate-50 px-4 py-12">
197
- <ResetPasswordForm
198
- token={token}
199
- title="Create new password"
200
- subtitle="Enter your new password below"
201
- className="w-full max-w-md rounded-2xl border border-slate-200 bg-white p-8 shadow-lg"
202
- formClassName="space-y-5"
203
- fieldClassName="space-y-2"
204
- labelClassName="block text-sm font-medium text-slate-700"
205
- inputClassName="w-full rounded-lg border border-slate-300 px-4 py-2 text-sm focus:border-blue-500 focus:ring-4 focus:ring-blue-100"
206
- buttonClassName="w-full rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700"
207
- submitButtonText="Update Password"
208
- loadingText="Updating..."
209
- onSuccess={() => navigate('/login')}
210
- />
211
- </div>
212
- );
213
- }
214
- ```
215
-
216
- ### VerifyEmailForm Component
217
-
218
- ```tsx
219
- import { VerifyEmailForm } from '@rqdhw3n/react-auth-flow';
220
- import { useSearchParams } from 'react-router-dom';
221
-
222
- function VerifyEmailPage() {
223
- const [searchParams] = useSearchParams();
224
- const token = searchParams.get('token') || '';
225
- const email = searchParams.get('email') || '';
226
-
227
- return (
228
- <div className="flex min-h-screen items-center justify-center bg-slate-50 px-4 py-12">
229
- <VerifyEmailForm
230
- token={token}
231
- email={email}
232
- title="Verify your email"
233
- subtitle="Enter the code sent to your email address"
234
- className="w-full max-w-md rounded-2xl border border-slate-200 bg-white p-8 shadow-lg"
235
- formClassName="space-y-5"
236
- fieldClassName="space-y-2"
237
- labelClassName="block text-sm font-medium text-slate-700"
238
- inputClassName="w-full rounded-lg border border-slate-300 px-4 py-2 text-sm focus:border-blue-500 focus:ring-4 focus:ring-blue-100"
239
- buttonClassName="w-full rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700"
240
- submitButtonText="Verify Email"
241
- loadingText="Verifying..."
242
- onSuccess={() => {
243
- alert('Email verified! You can now log in.');
244
- }}
245
- />
246
- </div>
247
- );
248
- }
249
- ```
250
-
251
- ### Simple Usage Without Custom Styling
252
-
253
- ```tsx
254
- // Forms work with default Tailwind-friendly styling
255
- <LoginForm
256
- onSuccess={() => navigate('/dashboard')}
257
- />
258
- ```
259
-
260
- ### ProtectedRoute Component
261
-
262
- ```tsx
263
- import { ProtectedRoute } from '@rqdhw3n/react-auth-flow';
264
- import { Routes, Route } from 'react-router-dom';
265
-
266
- function App() {
267
- return (
268
- <Routes>
269
- <Route path="/login" element={<LoginPage />} />
270
- <Route
271
- path="/dashboard"
272
- element={
273
- <ProtectedRoute redirectTo="/login">
274
- <Dashboard />
275
- </ProtectedRoute>
276
- }
277
- />
278
- <Route
279
- path="/admin"
280
- element={
281
- <ProtectedRoute
282
- roles={['admin']}
283
- redirectTo="/unauthorized"
284
- >
285
- <AdminPanel />
286
- </ProtectedRoute>
287
- }
288
- />
289
- <Route
290
- path="/manage-users"
291
- element={
292
- <ProtectedRoute
293
- permissions={['users.manage', 'users.delete']}
294
- redirectTo="/unauthorized"
295
- >
296
- <UserManagement />
297
- </ProtectedRoute>
298
- }
299
- />
300
- </Routes>
301
- );
302
- }
303
- ```
304
-
305
- ### useAuth Hook
306
-
307
- ```tsx
308
- import { useAuth } from '@rqdhw3n/react-auth-flow';
309
-
310
- function UserProfile() {
311
- const {
312
- user,
313
- isAuthenticated,
314
- isLoading,
315
- error,
316
- login,
317
- logout,
318
- refreshSession,
319
- setUser,
320
- } = useAuth();
321
-
322
- const handleLogin = async () => {
323
- try {
324
- const user = await login({
325
- email: 'user@example.com',
326
- password: 'password',
327
- rememberMe: true,
328
- });
329
- console.log('Logged in as:', user);
330
- } catch (err) {
331
- console.error('Login failed:', err);
332
- }
333
- };
334
-
335
- const handleLogout = async () => {
336
- await logout();
337
- console.log('Logged out');
338
- };
339
-
340
- if (isLoading) {
341
- return <div>Loading...</div>;
342
- }
343
-
344
- if (error) {
345
- return <div>Error: {error.message}</div>;
346
- }
347
-
348
- if (!isAuthenticated) {
349
- return <button onClick={handleLogin}>Login</button>;
350
- }
351
-
352
- return (
353
- <div>
354
- <h1>Hello, {user?.name}</h1>
355
- <p>Email: {user?.email}</p>
356
- <p>Roles: {user?.roles?.join(', ')}</p>
357
- <button onClick={handleLogout}>Logout</button>
358
- <button onClick={refreshSession}>Refresh Session</button>
359
- </div>
360
- );
361
- }
362
- ```
363
-
364
- ## API Endpoints Configuration
365
-
366
- The package expects your backend to provide the following endpoints by default:
367
-
368
- ### Default Endpoints
369
-
370
- - `POST /auth/login` - Login with email and password
371
- - `POST /auth/register` - Register a new account
372
- - `POST /auth/logout` - Logout the user
373
- - `GET /auth/me` - Get current user information
374
- - `POST /auth/refresh` - Refresh authentication token
375
- - `POST /auth/forgot-password` - Request password reset
376
- - `POST /auth/reset-password` - Reset password with token
377
- - `POST /auth/verify-email` - Verify email with token
378
-
379
- ### Customizing Endpoints
380
-
381
- ```tsx
382
- import { AuthProvider } from '@rqdhw3n/react-auth-flow';
383
-
384
- <AuthProvider
385
- baseURL="https://api.example.com"
386
- endpoints={{
387
- login: '/auth/signin',
388
- register: '/auth/signup',
389
- me: '/user/profile',
390
- // ... other endpoints
391
- }}
392
- >
393
- {/* Your app */}
394
- </AuthProvider>
395
- ```
396
-
397
- ## Expected API Response Formats
398
-
399
- ### Login Response
400
-
401
- ```json
402
- {
403
- "user": {
404
- "id": 1,
405
- "name": "John Doe",
406
- "email": "john@example.com",
407
- "roles": ["admin"],
408
- "permissions": ["users.manage", "users.delete"]
409
- }
410
- }
411
- ```
412
-
413
- ### Current User (Me) Response
414
-
415
- ```json
416
- {
417
- "user": {
418
- "id": 1,
419
- "name": "John Doe",
420
- "email": "john@example.com",
421
- "roles": ["admin"],
422
- "permissions": ["users.manage", "users.delete"]
423
- }
424
- }
425
- ```
426
-
427
- ### Error Response
428
-
429
- ```json
430
- {
431
- "error": {
432
- "code": "INVALID_CREDENTIALS",
433
- "message": "Invalid email or password",
434
- "statusCode": 401
435
- }
436
- }
437
- ```
438
-
439
- ## HttpOnly Cookie JWT Authentication
440
-
441
- For enhanced security, configure your backend to use HttpOnly cookies:
442
-
443
- ```tsx
444
- // Backend should set a cookie like:
445
- // Set-Cookie: jwt=token; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
446
-
447
- // The package will automatically include cookies with requests
448
- // because credentials: "include" is set by default
449
- ```
450
-
451
- ## Custom Headers and Request Adapter
452
-
453
- ```tsx
454
- import { createAuthClient } from '@rqdhw3n/react-auth-flow';
455
-
456
- // Create a custom client
457
- const authClient = createAuthClient({
458
- baseURL: 'https://api.example.com',
459
- headers: {
460
- 'X-API-Key': 'your-api-key',
461
- 'X-Client-Version': '1.0.0',
462
- },
463
- credentials: 'include', // for HttpOnly cookies
464
- adapter: async (url, options) => {
465
- // Custom request logic
466
- console.log('Making request to:', url);
467
- return fetch(url, options);
468
- },
469
- });
470
-
471
- // Use in AuthProvider
472
- <AuthProvider
473
- baseURL="https://api.example.com"
474
- // ... other config
475
- >
476
- {/* Your app */}
477
- </AuthProvider>
478
- ```
479
-
480
- ## TypeScript Customization
481
-
482
- Extend types for your application:
483
-
484
- ```tsx
485
- import { AuthUser, AuthContextValue } from '@rqdhw3n/react-auth-flow';
486
-
487
- // Extend the AuthUser type
488
- interface AppUser extends AuthUser {
489
- id: number;
490
- name: string;
491
- email: string;
492
- roles: string[];
493
- permissions: string[];
494
- company?: string;
495
- department?: string;
496
- }
497
-
498
- // Use in your components
499
- import { useAuth } from '@rqdhw3n/react-auth-flow';
500
-
501
- function MyComponent() {
502
- const { user } = useAuth();
503
- const appUser = user as AppUser;
504
-
505
- return <div>Working in {appUser.department}</div>;
506
- }
507
- ```
508
-
509
- ## Styling Components
510
-
511
- All form components use semantic class names for styling:
512
-
513
- ```css
514
- .auth-form-group {
515
- margin-bottom: 1rem;
516
- }
517
-
518
- .auth-form-label {
519
- display: block;
520
- margin-bottom: 0.5rem;
521
- font-weight: 500;
522
- }
523
-
524
- .auth-form-input {
525
- width: 100%;
526
- padding: 0.5rem;
527
- border: 1px solid #ccc;
528
- border-radius: 4px;
529
- font-size: 1rem;
530
- }
531
-
532
- .auth-form-input:disabled {
533
- background-color: #f5f5f5;
534
- cursor: not-allowed;
535
- }
536
-
537
- .auth-form-error {
538
- color: #dc3545;
539
- margin-top: 0.5rem;
540
- font-size: 0.875rem;
541
- }
542
-
543
- .auth-form-button {
544
- padding: 0.5rem 1rem;
545
- border: none;
546
- border-radius: 4px;
547
- font-size: 1rem;
548
- cursor: pointer;
549
- width: 100%;
550
- }
551
-
552
- .auth-form-button-primary {
553
- background-color: #007bff;
554
- color: white;
555
- }
556
-
557
- .auth-form-button-primary:hover {
558
- background-color: #0056b3;
559
- }
560
-
561
- .auth-form-button:disabled {
562
- opacity: 0.5;
563
- cursor: not-allowed;
564
- }
565
-
566
- .auth-form-checkbox {
567
- display: flex;
568
- align-items: center;
569
- gap: 0.5rem;
570
- }
571
-
572
- .auth-form-checkbox .auth-form-label {
573
- margin-bottom: 0;
574
- }
575
-
576
- .auth-form-success {
577
- padding: 1rem;
578
- background-color: #d4edda;
579
- border: 1px solid #c3e6cb;
580
- border-radius: 4px;
581
- color: #155724;
582
- }
583
-
584
- .auth-form-success-message {
585
- margin: 0;
586
- }
587
-
588
- .auth-loading {
589
- text-align: center;
590
- padding: 2rem;
591
- font-size: 1rem;
592
- }
593
-
594
- .auth-forbidden {
595
- padding: 2rem;
596
- text-align: center;
597
- color: #dc3545;
598
- }
599
- ```
600
-
601
- ## Error Handling
602
-
603
- The package normalizes all errors to a consistent format:
604
-
605
- ```tsx
606
- import { useAuth, AuthError } from '@rqdhw3n/react-auth-flow';
607
-
608
- function MyComponent() {
609
- const { error } = useAuth();
610
-
611
- if (error) {
612
- const authError: AuthError = error;
613
- console.log({
614
- code: authError.code, // e.g., "INVALID_CREDENTIALS"
615
- message: authError.message,
616
- statusCode: authError.statusCode, // e.g., 401
617
- details: authError.details, // additional error info
618
- });
619
- }
620
-
621
- return <div>Status: {error?.message}</div>;
622
- }
623
- ```
624
-
625
- ## License
626
-
627
- MIT
628
-
629
- ## Support
630
-
631
- 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.