topiray-auth-react 1.0.0

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 ADDED
@@ -0,0 +1,704 @@
1
+ # Topiray Auth React Component Library
2
+
3
+ A comprehensive, themeable React component library for authentication flows. Built with TypeScript, CSS Modules, and designed for maximum customization and accessibility.
4
+
5
+ ## Features
6
+
7
+ - 🎨 **Fully Themeable** - Customize colors, fonts, spacing, and more
8
+ - 🔧 **CSS Modules** - Strongly-typed, scoped styling
9
+ - 📱 **Responsive Design** - Mobile-first approach with breakpoint support
10
+ - ♿ **Accessible** - ARIA labels, keyboard navigation, focus management
11
+ - 🔒 **Complete Auth Flow** - Sign in/up, 2FA, email verification, password reset
12
+ - ⚡ **TypeScript** - Full type safety and IntelliSense support
13
+ - 🎯 **Tree Shakeable** - Import only what you need
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install topiray-auth-react
19
+ # or
20
+ yarn add topiray-auth-react
21
+ ```
22
+
23
+ ### Peer Dependencies
24
+
25
+ ```bash
26
+ npm install react react-dom lucide-react @mui/material
27
+ ```
28
+
29
+ ### CSS Import
30
+
31
+ **Important**: You must import the CSS file for proper styling:
32
+
33
+ ```tsx
34
+ // Import the CSS file in your main App component or index file
35
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
36
+ ```
37
+
38
+ Or if you're using a bundler that supports CSS imports:
39
+
40
+ ```css
41
+ /* In your main CSS file */
42
+ @import 'topiray-auth-react/dist/topiray-auth-react.css';
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```tsx
48
+ import React from 'react'
49
+ import {
50
+ ThemeProvider,
51
+ defaultTheme,
52
+ TwoPanelLayout,
53
+ AuthCard,
54
+ SignInForm
55
+ } from 'topiray-auth-react'
56
+
57
+ // Import the CSS file
58
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
59
+
60
+ function App() {
61
+ const handleSignIn = (email: string, password: string) => {
62
+ console.log('Sign in:', { email, password })
63
+ }
64
+
65
+ return (
66
+ <ThemeProvider theme={defaultTheme}>
67
+ <TwoPanelLayout
68
+ rightContent={
69
+ <AuthCard>
70
+ <SignInForm
71
+ onSubmit={handleSignIn}
72
+ onForgotPassword={() => console.log('Forgot password')}
73
+ onSignUp={() => console.log('Sign up')}
74
+ onSocialLogin={(provider) => console.log('Social:', provider)}
75
+ />
76
+ </AuthCard>
77
+ }
78
+ />
79
+ </ThemeProvider>
80
+ )
81
+ }
82
+ ```
83
+
84
+ ## Components
85
+
86
+ ### Auth Components
87
+
88
+ #### AuthCard
89
+ Container wrapper for auth forms with consistent styling.
90
+
91
+ ```tsx
92
+ import { AuthCard } from 'topiray-auth-react'
93
+
94
+ <AuthCard>
95
+ {/* Your auth form content */}
96
+ </AuthCard>
97
+ ```
98
+
99
+ #### SignInForm
100
+ Complete sign-in form with email/password and social login options.
101
+
102
+ ```tsx
103
+ import { SignInForm } from 'topiray-auth-react'
104
+
105
+ <SignInForm
106
+ onSubmit={(email, password) => handleSignIn(email, password)}
107
+ onForgotPassword={() => navigate('/forgot-password')}
108
+ onSignUp={() => navigate('/sign-up')}
109
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
110
+ isLoading={isSigningIn}
111
+ logoSrc="/your-logo.png"
112
+ />
113
+ ```
114
+
115
+ #### SignUpForm
116
+ Account creation form with business/individual selection.
117
+
118
+ ```tsx
119
+ import { SignUpForm } from 'topiray-auth-react'
120
+
121
+ <SignUpForm
122
+ onSubmit={(email, password, accountType) => handleSignUp(email, password, accountType)}
123
+ onSignIn={() => navigate('/sign-in')}
124
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
125
+ isLoading={isSigningUp}
126
+ />
127
+ ```
128
+
129
+ #### ForgottenPasswordForm
130
+ Password reset request form.
131
+
132
+ ```tsx
133
+ import { ForgottenPasswordForm } from 'topiray-auth-react'
134
+
135
+ <ForgottenPasswordForm
136
+ onSubmit={(email) => handlePasswordReset(email)}
137
+ isLoading={isLoading}
138
+ />
139
+ ```
140
+
141
+ #### VerifyEmailForm
142
+ Email verification flow with resend functionality.
143
+
144
+ ```tsx
145
+ import { VerifyEmailForm } from 'topiray-auth-react'
146
+
147
+ <VerifyEmailForm
148
+ onSubmit={() => navigate('/sign-in')}
149
+ onResendEmail={() => handleResendEmail()}
150
+ email="user@example.com"
151
+ isLoading={isLoading}
152
+ />
153
+ ```
154
+
155
+ ### Two-Factor Authentication
156
+
157
+ #### TwoFactorSetupForm
158
+ QR code setup for authenticator apps.
159
+
160
+ ```tsx
161
+ import { TwoFactorSetupForm } from 'topiray-auth-react'
162
+
163
+ <TwoFactorSetupForm
164
+ onNext={() => navigate('/2fa/verify')}
165
+ onCancel={() => navigate('/dashboard')}
166
+ qrCodeUri="otpauth://totp/App:user@example.com?secret=SECRET&issuer=App"
167
+ sharedKey="JBSWY3DPEHPK3PXP"
168
+ isLoading={isLoading}
169
+ />
170
+ ```
171
+
172
+ #### TwoFactorSetupEnterVerificationForm
173
+ 6-digit code entry with auto-focus and paste support.
174
+
175
+ ```tsx
176
+ import { TwoFactorSetupEnterVerificationForm } from 'topiray-auth-react'
177
+
178
+ <TwoFactorSetupEnterVerificationForm
179
+ onVerify={(code) => handleVerification(code)}
180
+ isLoading={isVerifying}
181
+ error={error}
182
+ backRoute="/2fa/setup"
183
+ />
184
+ ```
185
+
186
+ #### TwoFactorSetupCompleteForm
187
+ Backup codes display with copy/download functionality.
188
+
189
+ ```tsx
190
+ import { TwoFactorSetupCompleteForm } from 'topiray-auth-react'
191
+
192
+ <TwoFactorSetupCompleteForm
193
+ onDone={() => navigate('/dashboard')}
194
+ backupCodes={recoveryCodes}
195
+ isLoading={isLoading}
196
+ />
197
+ ```
198
+
199
+ ### Layout Components
200
+
201
+ #### TwoPanelLayout
202
+ Responsive layout with left branding panel and right content area.
203
+
204
+ ```tsx
205
+ import { TwoPanelLayout } from 'topiray-auth-react'
206
+
207
+ <TwoPanelLayout
208
+ leftContent={<YourBrandingContent />}
209
+ rightContent={<YourAuthForm />}
210
+ leftBackgroundImage="/background.jpg"
211
+ logoSrc="/logo.png"
212
+ />
213
+ ```
214
+
215
+ #### NavLinksLayout
216
+ Flexible content layout for pages with navigation.
217
+
218
+ ```tsx
219
+ import { NavLinksLayout } from 'topiray-auth-react'
220
+
221
+ <NavLinksLayout
222
+ middle={<MainContent />}
223
+ right={<SidebarContent />}
224
+ />
225
+ ```
226
+
227
+ ### Common Components
228
+
229
+ #### Button
230
+ Versatile button with loading states and variants.
231
+
232
+ ```tsx
233
+ import { Button } from 'topiray-auth-react'
234
+
235
+ <Button variant="primary" isLoading={isLoading} fullWidth>
236
+ Sign In
237
+ </Button>
238
+
239
+ <Button variant="secondary" icon="google">
240
+ Sign in with Google
241
+ </Button>
242
+ ```
243
+
244
+ #### AlertMessage
245
+ Dismissible alert messages for different states.
246
+
247
+ ```tsx
248
+ import { AlertMessage } from 'topiray-auth-react'
249
+
250
+ <AlertMessage
251
+ type="error"
252
+ message="Invalid credentials"
253
+ dismissible
254
+ onDismiss={() => setError(null)}
255
+ />
256
+ ```
257
+
258
+ #### SocialLoginButtons
259
+ Pre-configured social login buttons.
260
+
261
+ ```tsx
262
+ import { SocialLoginButtons } from 'topiray-auth-react'
263
+
264
+ <SocialLoginButtons
265
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
266
+ providers={['google', 'apple', 'facebook']}
267
+ orientation="vertical"
268
+ isLoading={isLoading}
269
+ />
270
+ ```
271
+
272
+ ## Real-World Usage Examples
273
+
274
+ ### Complete Sign-In Page
275
+
276
+ ```tsx
277
+ import React, { useState, useEffect } from 'react'
278
+ import { useNavigate, useLocation } from 'react-router-dom'
279
+ import {
280
+ ThemeProvider,
281
+ defaultTheme,
282
+ TwoPanelLayout,
283
+ AuthCard,
284
+ SignInForm,
285
+ AlertMessage
286
+ } from 'topiray-auth-react'
287
+
288
+ // Import the CSS file
289
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
290
+
291
+ function SignInPage() {
292
+ const navigate = useNavigate()
293
+ const location = useLocation()
294
+ const [error, setError] = useState<string | null>(null)
295
+ const [isLoading, setIsLoading] = useState(false)
296
+
297
+ // Get success message from registration
298
+ const successMessage = location.state?.message
299
+
300
+ const handleSignIn = async (email: string, password: string) => {
301
+ try {
302
+ setError(null)
303
+ setIsLoading(true)
304
+
305
+ const result = await signInAPI(email, password)
306
+
307
+ if (result.succeeded) {
308
+ navigate('/dashboard')
309
+ } else if (result.requiresTwoFactor) {
310
+ navigate('/2fa/signin', { state: { userId: result.userId } })
311
+ } else if (result.isNotAllowed) {
312
+ navigate(`/verify-email?email=${encodeURIComponent(email)}`)
313
+ } else {
314
+ setError('Invalid email or password.')
315
+ }
316
+ } catch (error) {
317
+ setError('An error occurred during sign in.')
318
+ } finally {
319
+ setIsLoading(false)
320
+ }
321
+ }
322
+
323
+ return (
324
+ <ThemeProvider theme={defaultTheme}>
325
+ <TwoPanelLayout
326
+ rightContent={
327
+ <AuthCard>
328
+ {successMessage && (
329
+ <AlertMessage message={successMessage} type="success" />
330
+ )}
331
+ {error && (
332
+ <AlertMessage message={error} type="error" />
333
+ )}
334
+ <SignInForm
335
+ onSubmit={handleSignIn}
336
+ onForgotPassword={() => navigate('/forgot-password')}
337
+ onSignUp={() => navigate('/sign-up')}
338
+ onSocialLogin={(provider) => handleSocialLogin(provider)}
339
+ isLoading={isLoading}
340
+ />
341
+ </AuthCard>
342
+ }
343
+ />
344
+ </ThemeProvider>
345
+ )
346
+ }
347
+ ```
348
+
349
+ ### Two-Factor Setup with QR Code
350
+
351
+ ```tsx
352
+ import React, { useEffect, useState } from 'react'
353
+ import { useNavigate } from 'react-router-dom'
354
+ import QRCode from 'qrcode'
355
+ import {
356
+ TwoPanelLayout,
357
+ AuthCard,
358
+ TwoFactorSetupForm,
359
+ AlertMessage
360
+ } from 'topiray-auth-react'
361
+
362
+ function TwoFactorSetupPage() {
363
+ const navigate = useNavigate()
364
+ const [qrCodeDataUrl, setQrCodeDataUrl] = useState<string | null>(null)
365
+ const [sharedKey, setSharedKey] = useState<string | null>(null)
366
+ const [error, setError] = useState<string | null>(null)
367
+ const [isLoading, setIsLoading] = useState(false)
368
+
369
+ useEffect(() => {
370
+ generateQRCode()
371
+ }, [])
372
+
373
+ const generateQRCode = async () => {
374
+ try {
375
+ setIsLoading(true)
376
+ const result = await createAuthenticatorKeyAPI()
377
+
378
+ if (result.authenticatorUri && result.sharedKey) {
379
+ const qrDataUrl = await QRCode.toDataURL(result.authenticatorUri, {
380
+ width: 200,
381
+ margin: 2
382
+ })
383
+
384
+ setQrCodeDataUrl(qrDataUrl)
385
+ setSharedKey(result.sharedKey)
386
+
387
+ // Render QR code
388
+ setTimeout(() => {
389
+ const container = document.getElementById('qr-code-container')
390
+ if (container && qrDataUrl) {
391
+ container.innerHTML = `<img src="${qrDataUrl}" alt="QR Code" />`
392
+ }
393
+ }, 100)
394
+ } else {
395
+ setError('Failed to generate QR code.')
396
+ }
397
+ } catch (error) {
398
+ setError('Failed to generate QR code.')
399
+ } finally {
400
+ setIsLoading(false)
401
+ }
402
+ }
403
+
404
+ return (
405
+ <TwoPanelLayout
406
+ rightContent={
407
+ <AuthCard>
408
+ {error && <AlertMessage message={error} type="error" />}
409
+ <TwoFactorSetupForm
410
+ onNext={() => navigate('/2fa/verify')}
411
+ onCancel={() => navigate('/dashboard')}
412
+ qrCodeUri={qrCodeDataUrl}
413
+ sharedKey={sharedKey}
414
+ isLoading={isLoading}
415
+ />
416
+ </AuthCard>
417
+ }
418
+ />
419
+ )
420
+ }
421
+ ```
422
+
423
+ ## Theming
424
+
425
+ ### Using Built-in Themes
426
+
427
+ ```tsx
428
+ import { ThemeProvider, defaultTheme, darkTheme } from 'topiray-auth-react'
429
+
430
+ // Light theme
431
+ <ThemeProvider theme={defaultTheme}>
432
+ <App />
433
+ </ThemeProvider>
434
+
435
+ // Dark theme
436
+ <ThemeProvider theme={darkTheme}>
437
+ <App />
438
+ </ThemeProvider>
439
+ ```
440
+
441
+ ### Creating Custom Themes
442
+
443
+ ```tsx
444
+ import { createCustomTheme } from 'topiray-auth-react'
445
+
446
+ const corporateTheme = createCustomTheme({
447
+ colors: {
448
+ primary: '#0066cc',
449
+ secondary: '#6b7280',
450
+ background: '#ffffff',
451
+ surface: '#f9fafb',
452
+ text: '#111827',
453
+ textSecondary: '#6b7280',
454
+ border: '#d1d5db',
455
+ success: '#10b981',
456
+ warning: '#f59e0b',
457
+ error: '#ef4444',
458
+ info: '#3b82f6',
459
+ hover: '#f3f4f6',
460
+ active: '#e5e7eb',
461
+ disabled: '#9ca3af',
462
+ inputBackground: '#ffffff',
463
+ inputBorder: '#d1d5db',
464
+ inputText: '#111827',
465
+ inputPlaceholder: '#9ca3af',
466
+ buttonPrimary: '#0066cc',
467
+ buttonPrimaryText: '#ffffff',
468
+ buttonSecondary: '#6b7280',
469
+ buttonSecondaryText: '#ffffff',
470
+ buttonSocial: '#374151',
471
+ buttonSocialText: '#ffffff'
472
+ },
473
+ brand: {
474
+ logo: '/corporate-logo.png',
475
+ logoAlt: 'Corporate Logo'
476
+ },
477
+ customization: {
478
+ showFormHeader: true,
479
+ showSocialLogin: true,
480
+ showBackArrow: true,
481
+ showLogo: true,
482
+ roundedCorners: true,
483
+ animations: true
484
+ }
485
+ })
486
+
487
+ <ThemeProvider theme={corporateTheme}>
488
+ <App />
489
+ </ThemeProvider>
490
+ ```
491
+
492
+ ### Advanced Theme Customization
493
+
494
+ ```tsx
495
+ const advancedTheme = createCustomTheme({
496
+ colors: {
497
+ // Custom color palette
498
+ primary: '#7c3aed',
499
+ secondary: '#64748b',
500
+ // ... other colors
501
+ },
502
+ components: {
503
+ spacing: {
504
+ xs: '0.25rem',
505
+ sm: '0.5rem',
506
+ md: '1rem',
507
+ lg: '1.5rem',
508
+ xl: '2rem'
509
+ },
510
+ borderRadius: {
511
+ sm: '0.25rem',
512
+ md: '0.5rem',
513
+ lg: '0.75rem',
514
+ xl: '1rem'
515
+ },
516
+ typography: {
517
+ fontFamily: '"Inter", system-ui, sans-serif',
518
+ fontSize: {
519
+ xs: '0.75rem',
520
+ sm: '0.875rem',
521
+ md: '1rem',
522
+ lg: '1.125rem',
523
+ xl: '1.25rem',
524
+ xxl: '1.5rem'
525
+ }
526
+ }
527
+ },
528
+ customization: {
529
+ backgroundImage: '/custom-background.jpg',
530
+ leftPanelContent: <CustomBrandingComponent />
531
+ }
532
+ })
533
+ ```
534
+
535
+ ## CSS Custom Properties
536
+
537
+ The library uses CSS custom properties for theming. Make sure to import the CSS file first, then you can override these properties:
538
+
539
+ ```tsx
540
+ // First, import the CSS file
541
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
542
+ ```
543
+
544
+ ```css
545
+ /* Then override custom properties in your CSS */
546
+ :root {
547
+ --topiray-color-primary: #your-brand-color;
548
+ --topiray-color-surface: #your-surface-color;
549
+ --topiray-font-family: 'Your Font', sans-serif;
550
+ --topiray-radius-md: 12px;
551
+ --topiray-spacing-lg: 24px;
552
+ }
553
+ ```
554
+
555
+ ## Integration Patterns
556
+
557
+ ### With React Router
558
+
559
+ ```tsx
560
+ import { BrowserRouter, Routes, Route } from 'react-router-dom'
561
+
562
+ // Import the CSS file once at the app level
563
+ import 'topiray-auth-react/dist/topiray-auth-react.css'
564
+
565
+ function App() {
566
+ return (
567
+ <ThemeProvider theme={defaultTheme}>
568
+ <BrowserRouter>
569
+ <Routes>
570
+ <Route path="/signin" element={<SignInPage />} />
571
+ <Route path="/signup" element={<SignUpPage />} />
572
+ <Route path="/forgot-password" element={<ForgotPasswordPage />} />
573
+ <Route path="/verify-email" element={<VerifyEmailPage />} />
574
+ <Route path="/2fa/setup" element={<TwoFactorSetupPage />} />
575
+ <Route path="/2fa/verify" element={<TwoFactorVerifyPage />} />
576
+ <Route path="/2fa/complete" element={<TwoFactorCompletePage />} />
577
+ </Routes>
578
+ </BrowserRouter>
579
+ </ThemeProvider>
580
+ )
581
+ }
582
+ ```
583
+
584
+ ### With State Management
585
+
586
+ ```tsx
587
+ // Using React Context
588
+ const AuthContext = createContext()
589
+
590
+ function AuthProvider({ children }) {
591
+ const [user, setUser] = useState(null)
592
+ const [isLoading, setIsLoading] = useState(false)
593
+
594
+ const login = async (email, password) => {
595
+ setIsLoading(true)
596
+ try {
597
+ const result = await signInAPI(email, password)
598
+ setUser(result.user)
599
+ return result
600
+ } finally {
601
+ setIsLoading(false)
602
+ }
603
+ }
604
+
605
+ return (
606
+ <AuthContext.Provider value={{ user, isLoading, login }}>
607
+ {children}
608
+ </AuthContext.Provider>
609
+ )
610
+ }
611
+ ```
612
+
613
+ ### With Form Validation
614
+
615
+ ```tsx
616
+ import { z } from 'zod'
617
+
618
+ const signInSchema = z.object({
619
+ email: z.string().email('Invalid email address'),
620
+ password: z.string().min(8, 'Password must be at least 8 characters')
621
+ })
622
+
623
+ function SignInPage() {
624
+ const [errors, setErrors] = useState({})
625
+
626
+ const handleSignIn = (email, password) => {
627
+ try {
628
+ signInSchema.parse({ email, password })
629
+ setErrors({})
630
+ // Proceed with sign in
631
+ } catch (error) {
632
+ setErrors(error.flatten().fieldErrors)
633
+ }
634
+ }
635
+
636
+ return (
637
+ <SignInForm
638
+ onSubmit={handleSignIn}
639
+ // Pass validation errors to form
640
+ />
641
+ )
642
+ }
643
+ ```
644
+
645
+ ## TypeScript Support
646
+
647
+ Full TypeScript support with comprehensive type definitions:
648
+
649
+ ```tsx
650
+ import type {
651
+ ThemeConfig,
652
+ SignInFormProps,
653
+ AuthCardProps
654
+ } from 'topiray-auth-react'
655
+
656
+ // Custom theme with full type safety
657
+ const myTheme: ThemeConfig = {
658
+ colors: {
659
+ primary: '#0066cc',
660
+ // ... TypeScript will validate all required properties
661
+ },
662
+ // ... rest of theme configuration
663
+ }
664
+
665
+ // Component props are fully typed
666
+ const handleSignIn: SignInFormProps['onSubmit'] = (email, password) => {
667
+ // email and password are properly typed as strings
668
+ }
669
+ ```
670
+
671
+ ## Accessibility Features
672
+
673
+ - **Keyboard Navigation**: Full keyboard support for all interactive elements
674
+ - **Screen Reader Support**: Proper ARIA labels and descriptions
675
+ - **Focus Management**: Logical focus flow and focus trapping in modals
676
+ - **High Contrast**: Colors meet WCAG contrast requirements
677
+ - **Reduced Motion**: Respects user's motion preferences
678
+
679
+ ## Browser Support
680
+
681
+ - Chrome 90+
682
+ - Firefox 88+
683
+ - Safari 14+
684
+ - Edge 90+
685
+
686
+ ## Contributing
687
+
688
+ 1. Fork the repository
689
+ 2. Create a feature branch
690
+ 3. Make your changes
691
+ 4. Add tests for new functionality
692
+ 5. Submit a pull request
693
+
694
+
695
+ ## Support
696
+
697
+ For questions and support:
698
+ - Create an issue on GitHub
699
+ - Check the documentation
700
+ - Review the demo application
701
+
702
+ ---
703
+
704
+ Built with ❤️ for the React community