@beyondcorp/beyond-ui 1.0.19 → 1.0.20
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/Alert/Alert.example.d.ts +2 -0
- package/dist/components/Alert/Alert.example.js +7 -0
- package/dist/components/Alert/Alert.example.js.map +1 -0
- package/dist/components/Auth/AuthShowcase.d.ts +5 -0
- package/dist/components/Auth/AuthShowcase.js +105 -0
- package/dist/components/Auth/AuthShowcase.js.map +1 -0
- package/dist/components/Auth/LoginForm.d.ts +12 -0
- package/dist/components/Auth/LoginForm.example.d.ts +2 -0
- package/dist/components/Auth/LoginForm.example.js +9 -0
- package/dist/components/Auth/LoginForm.example.js.map +1 -0
- package/dist/components/Auth/LoginForm.js +48 -0
- package/dist/components/Auth/LoginForm.js.map +1 -0
- package/dist/components/Auth/PasswordResetForm.d.ts +9 -0
- package/dist/components/Auth/PasswordResetForm.example.d.ts +2 -0
- package/dist/components/Auth/PasswordResetForm.example.js +20 -0
- package/dist/components/Auth/PasswordResetForm.example.js.map +1 -0
- package/dist/components/Auth/PasswordResetForm.js +30 -0
- package/dist/components/Auth/PasswordResetForm.js.map +1 -0
- package/dist/components/Auth/ProtectedRoute.d.ts +14 -0
- package/dist/components/Auth/ProtectedRoute.example.d.ts +7 -0
- package/dist/components/Auth/ProtectedRoute.example.js +16 -0
- package/dist/components/Auth/ProtectedRoute.example.js.map +1 -0
- package/dist/components/Auth/ProtectedRoute.js +33 -0
- package/dist/components/Auth/ProtectedRoute.js.map +1 -0
- package/dist/components/Auth/SignupForm.d.ts +11 -0
- package/dist/components/Auth/SignupForm.example.d.ts +2 -0
- package/dist/components/Auth/SignupForm.example.js +9 -0
- package/dist/components/Auth/SignupForm.example.js.map +1 -0
- package/dist/components/Auth/SignupForm.js +59 -0
- package/dist/components/Auth/SignupForm.js.map +1 -0
- package/dist/components/Avatar/Avatar.example.d.ts +2 -0
- package/dist/components/Avatar/Avatar.example.js +7 -0
- package/dist/components/Avatar/Avatar.example.js.map +1 -0
- package/dist/components/Badge/Badge.example.d.ts +2 -0
- package/dist/components/Badge/Badge.example.js +7 -0
- package/dist/components/Badge/Badge.example.js.map +1 -0
- package/dist/components/Button/Button.example.d.ts +2 -0
- package/dist/components/Button/Button.example.js +7 -0
- package/dist/components/Button/Button.example.js.map +1 -0
- package/dist/components/Card/Card.example.d.ts +2 -0
- package/dist/components/Card/Card.example.js +7 -0
- package/dist/components/Card/Card.example.js.map +1 -0
- package/dist/components/Checkbox/Checkbox.example.d.ts +2 -0
- package/dist/components/Checkbox/Checkbox.example.js +7 -0
- package/dist/components/Checkbox/Checkbox.example.js.map +1 -0
- package/dist/components/ComponentShowcase/ComponentShowcase.js +34 -435
- package/dist/components/ComponentShowcase/ComponentShowcase.js.map +1 -1
- package/dist/components/ComponentShowcase/componentDocs.d.ts +225 -0
- package/dist/components/ComponentShowcase/componentDocs.js +205 -0
- package/dist/components/ComponentShowcase/componentDocs.js.map +1 -0
- package/dist/components/ComponentShowcase/showcaseRegistry.d.ts +1 -0
- package/dist/components/ComponentShowcase/showcaseRegistry.js +64 -0
- package/dist/components/ComponentShowcase/showcaseRegistry.js.map +1 -0
- package/dist/components/DashboardGrid/DashboardGrid.example.d.ts +2 -0
- package/dist/components/DashboardGrid/DashboardGrid.example.js +7 -0
- package/dist/components/DashboardGrid/DashboardGrid.example.js.map +1 -0
- package/dist/components/DashboardHeader/DashboardHeader.example.d.ts +2 -0
- package/dist/components/DashboardHeader/DashboardHeader.example.js +7 -0
- package/dist/components/DashboardHeader/DashboardHeader.example.js.map +1 -0
- package/dist/components/DashboardLayout/DashboardLayout.example.d.ts +2 -0
- package/dist/components/DashboardLayout/DashboardLayout.example.js +7 -0
- package/dist/components/DashboardLayout/DashboardLayout.example.js.map +1 -0
- package/dist/components/Input/Input.example.d.ts +2 -0
- package/dist/components/Input/Input.example.js +7 -0
- package/dist/components/Input/Input.example.js.map +1 -0
- package/dist/components/Modal/Modal.example.d.ts +2 -0
- package/dist/components/Modal/Modal.example.js +12 -0
- package/dist/components/Modal/Modal.example.js.map +1 -0
- package/dist/components/Navbar/Navbar.d.ts +1 -1
- package/dist/components/Navbar/Navbar.example.d.ts +2 -0
- package/dist/components/Navbar/Navbar.example.js +7 -0
- package/dist/components/Navbar/Navbar.example.js.map +1 -0
- package/dist/components/Sidebar/Sidebar.example.d.ts +2 -0
- package/dist/components/Sidebar/Sidebar.example.js +21 -0
- package/dist/components/Sidebar/Sidebar.example.js.map +1 -0
- package/dist/components/Skeleton/Skeleton.example.d.ts +2 -0
- package/dist/components/Skeleton/Skeleton.example.js +7 -0
- package/dist/components/Skeleton/Skeleton.example.js.map +1 -0
- package/dist/components/Spinner/Spinner.example.d.ts +2 -0
- package/dist/components/Spinner/Spinner.example.js +8 -0
- package/dist/components/Spinner/Spinner.example.js.map +1 -0
- package/dist/components/StatsCard/StatsCard.example.d.ts +2 -0
- package/dist/components/StatsCard/StatsCard.example.js +16 -0
- package/dist/components/StatsCard/StatsCard.example.js.map +1 -0
- package/dist/components/Switch/Switch.example.d.ts +2 -0
- package/dist/components/Switch/Switch.example.js +7 -0
- package/dist/components/Switch/Switch.example.js.map +1 -0
- package/dist/components/Tabs/Tabs.example.d.ts +2 -0
- package/dist/components/Tabs/Tabs.example.js +11 -0
- package/dist/components/Tabs/Tabs.example.js.map +1 -0
- package/dist/components/Textarea/Textarea.example.d.ts +2 -0
- package/dist/components/Textarea/Textarea.example.js +7 -0
- package/dist/components/Textarea/Textarea.example.js.map +1 -0
- package/dist/components/Toast/Toast.example.d.ts +2 -0
- package/dist/components/Toast/Toast.example.js +8 -0
- package/dist/components/Toast/Toast.example.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/utils/validation.d.ts +21 -0
- package/dist/utils/validation.js +65 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +9 -3
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Alert, AlertTitle, AlertDescription } from './Alert.js';
|
|
3
|
+
|
|
4
|
+
const AlertExample = () => (jsxs("div", { className: "space-y-4", children: [jsxs(Alert, { variant: "info", children: [jsx(AlertTitle, { children: "Information" }), jsx(AlertDescription, { children: "This is an informational alert message." })] }), jsxs(Alert, { variant: "success", children: [jsx(AlertTitle, { children: "Success" }), jsx(AlertDescription, { children: "Operation completed successfully!" })] }), jsxs(Alert, { variant: "warning", children: [jsx(AlertTitle, { children: "Warning" }), jsx(AlertDescription, { children: "Please review your input before proceeding." })] }), jsxs(Alert, { variant: "danger", children: [jsx(AlertTitle, { children: "Error" }), jsx(AlertDescription, { children: "Something went wrong. Please try again." })] })] }));
|
|
5
|
+
|
|
6
|
+
export { AlertExample };
|
|
7
|
+
//# sourceMappingURL=Alert.example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.example.js","sources":["../../../src/components/Alert/Alert.example.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport { Alert, AlertTitle, AlertDescription } from \"./Alert\";\r\n\r\nexport const AlertExample: React.FC = () => (\r\n <div className=\"space-y-4\">\r\n <Alert variant=\"info\">\r\n <AlertTitle>Information</AlertTitle>\r\n <AlertDescription>This is an informational alert message.</AlertDescription>\r\n </Alert>\r\n <Alert variant=\"success\">\r\n <AlertTitle>Success</AlertTitle>\r\n <AlertDescription>Operation completed successfully!</AlertDescription>\r\n </Alert>\r\n <Alert variant=\"warning\">\r\n <AlertTitle>Warning</AlertTitle>\r\n <AlertDescription>Please review your input before proceeding.</AlertDescription>\r\n </Alert>\r\n <Alert variant=\"danger\">\r\n <AlertTitle>Error</AlertTitle>\r\n <AlertDescription>Something went wrong. Please try again.</AlertDescription>\r\n </Alert>\r\n </div>\r\n);"],"names":["_jsxs","_jsx"],"mappings":";;;AAGO,MAAM,YAAY,GAAa,OACpCA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,WAAW,EAAA,QAAA,EAAA,CACxBA,IAAA,CAAC,KAAK,IAAC,OAAO,EAAC,MAAM,EAAA,QAAA,EAAA,CACnBC,IAAC,UAAU,EAAA,EAAA,QAAA,EAAA,aAAA,EAAA,CAAyB,EACpCA,GAAA,CAAC,gBAAgB,EAAA,EAAA,QAAA,EAAA,yCAAA,EAAA,CAA2D,CAAA,EAAA,CACtE,EACRD,IAAA,CAAC,KAAK,EAAA,EAAC,OAAO,EAAC,SAAS,EAAA,QAAA,EAAA,CACtBC,IAAC,UAAU,EAAA,EAAA,QAAA,EAAA,SAAA,EAAA,CAAqB,EAChCA,GAAA,CAAC,gBAAgB,EAAA,EAAA,QAAA,EAAA,mCAAA,EAAA,CAAqD,CAAA,EAAA,CAChE,EACRD,IAAA,CAAC,KAAK,EAAA,EAAC,OAAO,EAAC,SAAS,aACtBC,GAAA,CAAC,UAAU,EAAA,EAAA,QAAA,EAAA,SAAA,EAAA,CAAqB,EAChCA,IAAC,gBAAgB,EAAA,EAAA,QAAA,EAAA,6CAAA,EAAA,CAA+D,CAAA,EAAA,CAC1E,EACRD,KAAC,KAAK,EAAA,EAAC,OAAO,EAAC,QAAQ,EAAA,QAAA,EAAA,CACrBC,GAAA,CAAC,UAAU,EAAA,EAAA,QAAA,EAAA,OAAA,EAAA,CAAmB,EAC9BA,GAAA,CAAC,gBAAgB,0DAA2D,CAAA,EAAA,CACtE,CAAA,EAAA,CACJ;;;;"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Shield, Eye, Code, Settings, Lock, UserPlus } from 'lucide-react';
|
|
4
|
+
import { Card, CardHeader, CardTitle, CardContent } from '../Card/Card.js';
|
|
5
|
+
import { Button } from '../Button/Button.js';
|
|
6
|
+
import { Badge } from '../Badge/Badge.js';
|
|
7
|
+
import { Tabs, TabsList, TabsTrigger, TabsContent } from '../Tabs/Tabs.js';
|
|
8
|
+
import { LoginForm } from './LoginForm.js';
|
|
9
|
+
import { SignupForm } from './SignupForm.js';
|
|
10
|
+
import { AuthProvider, useAuth } from '../../contexts/AuthContext.js';
|
|
11
|
+
import { showToast } from '../Toast/Toast.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Component to display current authentication state
|
|
15
|
+
*/
|
|
16
|
+
const AuthStatus = () => {
|
|
17
|
+
const { user, isAuthenticated, logout } = useAuth();
|
|
18
|
+
if (!isAuthenticated || !user) {
|
|
19
|
+
return (jsx(Card, { children: jsxs(CardContent, { className: "p-6 text-center", children: [jsx(Shield, { className: "h-12 w-12 text-gray-400 mx-auto mb-4" }), jsx("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: "Not Authenticated" }), jsx("p", { className: "text-gray-600", children: "Please log in to see your authentication status" })] }) }));
|
|
20
|
+
}
|
|
21
|
+
return (jsxs(Card, { children: [jsx(CardHeader, { children: jsxs(CardTitle, { className: "flex items-center", children: [jsx(Shield, { className: "h-5 w-5 text-success-600 mr-2" }), "Authentication Status"] }) }), jsxs(CardContent, { className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between", children: [jsx("span", { className: "text-sm font-medium text-gray-700", children: "Status:" }), jsx(Badge, { variant: "success", children: "Authenticated" })] }), jsxs("div", { className: "flex items-center justify-between", children: [jsx("span", { className: "text-sm font-medium text-gray-700", children: "User:" }), jsx("span", { className: "text-sm text-gray-900", children: user.name })] }), jsxs("div", { className: "flex items-center justify-between", children: [jsx("span", { className: "text-sm font-medium text-gray-700", children: "Email:" }), jsx("span", { className: "text-sm text-gray-900", children: user.email })] }), jsxs("div", { className: "flex items-center justify-between", children: [jsx("span", { className: "text-sm font-medium text-gray-700", children: "Role:" }), jsx(Badge, { variant: "outline", children: user.role })] }), jsx("div", { className: "pt-4 border-t", children: jsx(Button, { variant: "outline", onClick: logout, className: "w-full", children: "Sign Out" }) })] })] }));
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Code examples for the authentication components
|
|
25
|
+
*/
|
|
26
|
+
const codeExamples = {
|
|
27
|
+
login: `import { LoginForm } from '@/components/Auth';
|
|
28
|
+
|
|
29
|
+
function LoginPage() {
|
|
30
|
+
return (
|
|
31
|
+
<LoginForm
|
|
32
|
+
onSuccess={() => {
|
|
33
|
+
console.log('Login successful!');
|
|
34
|
+
// Redirect to dashboard
|
|
35
|
+
}}
|
|
36
|
+
onForgotPassword={() => {
|
|
37
|
+
// Handle forgot password
|
|
38
|
+
}}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
}`,
|
|
42
|
+
signup: `import { SignupForm } from '@/components/Auth';
|
|
43
|
+
|
|
44
|
+
function SignupPage() {
|
|
45
|
+
return (
|
|
46
|
+
<SignupForm
|
|
47
|
+
onSuccess={() => {
|
|
48
|
+
console.log('Signup successful!');
|
|
49
|
+
// Redirect to dashboard
|
|
50
|
+
}}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}`,
|
|
54
|
+
provider: `import { AuthProvider } from '@/contexts/AuthContext';
|
|
55
|
+
|
|
56
|
+
function App() {
|
|
57
|
+
return (
|
|
58
|
+
<AuthProvider>
|
|
59
|
+
<Router>
|
|
60
|
+
<Routes>
|
|
61
|
+
<Route path="/login" element={<LoginPage />} />
|
|
62
|
+
<Route path="/signup" element={<SignupPage />} />
|
|
63
|
+
<Route
|
|
64
|
+
path="/dashboard"
|
|
65
|
+
element={
|
|
66
|
+
<ProtectedRoute>
|
|
67
|
+
<Dashboard />
|
|
68
|
+
</ProtectedRoute>
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
</Routes>
|
|
72
|
+
</Router>
|
|
73
|
+
</AuthProvider>
|
|
74
|
+
);
|
|
75
|
+
}`,
|
|
76
|
+
protected: `import { ProtectedRoute } from '@/components/Auth';
|
|
77
|
+
|
|
78
|
+
function AdminPanel() {
|
|
79
|
+
return (
|
|
80
|
+
<ProtectedRoute requiredRole="admin">
|
|
81
|
+
<div>Admin-only content</div>
|
|
82
|
+
</ProtectedRoute>
|
|
83
|
+
);
|
|
84
|
+
}`,
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* AuthShowcase component demonstrating all authentication features
|
|
88
|
+
*/
|
|
89
|
+
const AuthShowcase = () => {
|
|
90
|
+
const [activeTab, setActiveTab] = useState('demo');
|
|
91
|
+
const [authMode, setAuthMode] = useState('login');
|
|
92
|
+
const copyToClipboard = async (code) => {
|
|
93
|
+
try {
|
|
94
|
+
await navigator.clipboard.writeText(code);
|
|
95
|
+
showToast.success('Code copied to clipboard!');
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
showToast.error('Failed to copy code');
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
return (jsx(AuthProvider, { children: jsxs("div", { className: "space-y-6", children: [jsxs("div", { className: "flex items-center justify-between", children: [jsxs("div", { children: [jsx("h1", { className: "text-2xl font-bold text-gray-900", children: "Authentication Components" }), jsx("p", { className: "text-gray-600 mt-1", children: "Comprehensive authentication system with forms, validation, and protection" })] }), jsxs(Badge, { variant: "outline", className: "flex items-center", children: [jsx(Shield, { className: "h-4 w-4 mr-1" }), "Secure"] })] }), jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, children: [jsxs(TabsList, { children: [jsxs(TabsTrigger, { value: "demo", children: [jsx(Eye, { className: "h-4 w-4 mr-2" }), "Demo"] }), jsxs(TabsTrigger, { value: "code", children: [jsx(Code, { className: "h-4 w-4 mr-2" }), "Code Examples"] }), jsxs(TabsTrigger, { value: "features", children: [jsx(Settings, { className: "h-4 w-4 mr-2" }), "Features"] })] }), jsx(TabsContent, { value: "demo", className: "mt-6", children: jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [jsx("div", { children: jsxs(Card, { children: [jsx(CardHeader, { children: jsxs("div", { className: "flex items-center justify-between", children: [jsx(CardTitle, { children: "Authentication Forms" }), jsxs("div", { className: "flex bg-gray-100 rounded-lg p-1", children: [jsxs(Button, { variant: authMode === 'login' ? 'primary' : 'ghost', size: "sm", onClick: () => setAuthMode('login'), children: [jsx(Lock, { className: "h-4 w-4 mr-1" }), "Login"] }), jsxs(Button, { variant: authMode === 'signup' ? 'primary' : 'ghost', size: "sm", onClick: () => setAuthMode('signup'), children: [jsx(UserPlus, { className: "h-4 w-4 mr-1" }), "Signup"] })] })] }) }), jsx(CardContent, { children: authMode === 'login' ? (jsx(LoginForm, { onSuccess: () => showToast.success('Login successful!'), onForgotPassword: () => showToast.info('Forgot password clicked'), onSignupClick: () => setAuthMode('signup') })) : (jsx(SignupForm, { onSuccess: () => showToast.success('Signup successful!'), onLoginClick: () => setAuthMode('login') })) })] }) }), jsx("div", { children: jsx(AuthStatus, {}) })] }) }), jsx(TabsContent, { value: "code", className: "mt-6", children: jsx("div", { className: "space-y-6", children: Object.entries(codeExamples).map(([key, code]) => (jsxs(Card, { children: [jsxs(CardHeader, { className: "flex flex-row items-center justify-between", children: [jsxs(CardTitle, { className: "capitalize", children: [key, " Example"] }), jsx(Button, { variant: "outline", size: "sm", onClick: () => copyToClipboard(code), children: "Copy Code" })] }), jsx(CardContent, { children: jsx("pre", { className: "bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm", children: jsx("code", { children: code }) }) })] }, key))) }) }), jsx(TabsContent, { value: "features", className: "mt-6", children: jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-6", children: [jsxs(Card, { children: [jsx(CardHeader, { children: jsx(CardTitle, { children: "LoginForm Features" }) }), jsx(CardContent, { children: jsxs("ul", { className: "space-y-2 text-sm text-gray-600", children: [jsx("li", { children: "\u2022 Email/password validation with Zod schema" }), jsx("li", { children: "\u2022 Password visibility toggle" }), jsx("li", { children: "\u2022 \"Remember me\" functionality" }), jsx("li", { children: "\u2022 Loading states and error handling" }), jsx("li", { children: "\u2022 ARIA labels for accessibility" }), jsx("li", { children: "\u2022 Keyboard navigation support" }), jsx("li", { children: "\u2022 Demo credentials provided" })] }) })] }), jsxs(Card, { children: [jsx(CardHeader, { children: jsx(CardTitle, { children: "SignupForm Features" }) }), jsx(CardContent, { children: jsxs("ul", { className: "space-y-2 text-sm text-gray-600", children: [jsx("li", { children: "\u2022 Real-time form validation" }), jsx("li", { children: "\u2022 Password strength indicator" }), jsx("li", { children: "\u2022 Password confirmation matching" }), jsx("li", { children: "\u2022 Terms of service acceptance" }), jsx("li", { children: "\u2022 Email uniqueness validation" }), jsx("li", { children: "\u2022 Responsive design" }), jsx("li", { children: "\u2022 Error boundary protection" })] }) })] }), jsxs(Card, { children: [jsx(CardHeader, { children: jsx(CardTitle, { children: "AuthProvider Features" }) }), jsx(CardContent, { children: jsxs("ul", { className: "space-y-2 text-sm text-gray-600", children: [jsx("li", { children: "\u2022 Context-based state management" }), jsx("li", { children: "\u2022 Token persistence with cookies" }), jsx("li", { children: "\u2022 Automatic token refresh" }), jsx("li", { children: "\u2022 Session management" }), jsx("li", { children: "\u2022 Error handling and recovery" }), jsx("li", { children: "\u2022 TypeScript support" }), jsx("li", { children: "\u2022 Secure cookie configuration" })] }) })] }), jsxs(Card, { children: [jsx(CardHeader, { children: jsx(CardTitle, { children: "ProtectedRoute Features" }) }), jsx(CardContent, { children: jsxs("ul", { className: "space-y-2 text-sm text-gray-600", children: [jsx("li", { children: "\u2022 Authentication checking" }), jsx("li", { children: "\u2022 Role-based access control" }), jsx("li", { children: "\u2022 Automatic redirects" }), jsx("li", { children: "\u2022 Loading states" }), jsx("li", { children: "\u2022 Custom fallback components" }), jsx("li", { children: "\u2022 Location state preservation" }), jsx("li", { children: "\u2022 HOC pattern support" })] }) })] })] }) })] })] }) }));
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export { AuthShowcase };
|
|
105
|
+
//# sourceMappingURL=AuthShowcase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthShowcase.js","sources":["../../../src/components/Auth/AuthShowcase.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Shield, Lock, UserPlus, Eye, Code, Settings } from 'lucide-react';\nimport { Card, CardHeader, CardTitle, CardContent } from '../Card';\nimport { Button } from '../Button';\nimport { Badge } from '../Badge';\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '../Tabs';\nimport { LoginForm } from './LoginForm';\nimport { SignupForm } from './SignupForm';\nimport { AuthProvider, useAuth } from '../../contexts/AuthContext';\nimport { showToast } from '../Toast';\n\n/**\n * Component to display current authentication state\n */\nconst AuthStatus: React.FC = () => {\n const { user, isAuthenticated, logout } = useAuth();\n\n if (!isAuthenticated || !user) {\n return (\n <Card>\n <CardContent className=\"p-6 text-center\">\n <Shield className=\"h-12 w-12 text-gray-400 mx-auto mb-4\" />\n <h3 className=\"text-lg font-semibold text-gray-900 mb-2\">\n Not Authenticated\n </h3>\n <p className=\"text-gray-600\">\n Please log in to see your authentication status\n </p>\n </CardContent>\n </Card>\n );\n }\n\n return (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center\">\n <Shield className=\"h-5 w-5 text-success-600 mr-2\" />\n Authentication Status\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-gray-700\">Status:</span>\n <Badge variant=\"success\">Authenticated</Badge>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-gray-700\">User:</span>\n <span className=\"text-sm text-gray-900\">{user.name}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-gray-700\">Email:</span>\n <span className=\"text-sm text-gray-900\">{user.email}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-gray-700\">Role:</span>\n <Badge variant=\"outline\">{user.role}</Badge>\n </div>\n <div className=\"pt-4 border-t\">\n <Button\n variant=\"outline\"\n onClick={logout}\n className=\"w-full\"\n >\n Sign Out\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n};\n\n/**\n * Code examples for the authentication components\n */\nconst codeExamples = {\n login: `import { LoginForm } from '@/components/Auth';\n\nfunction LoginPage() {\n return (\n <LoginForm\n onSuccess={() => {\n console.log('Login successful!');\n // Redirect to dashboard\n }}\n onForgotPassword={() => {\n // Handle forgot password\n }}\n />\n );\n}`,\n signup: `import { SignupForm } from '@/components/Auth';\n\nfunction SignupPage() {\n return (\n <SignupForm\n onSuccess={() => {\n console.log('Signup successful!');\n // Redirect to dashboard\n }}\n />\n );\n}`,\n provider: `import { AuthProvider } from '@/contexts/AuthContext';\n\nfunction App() {\n return (\n <AuthProvider>\n <Router>\n <Routes>\n <Route path=\"/login\" element={<LoginPage />} />\n <Route path=\"/signup\" element={<SignupPage />} />\n <Route\n path=\"/dashboard\"\n element={\n <ProtectedRoute>\n <Dashboard />\n </ProtectedRoute>\n }\n />\n </Routes>\n </Router>\n </AuthProvider>\n );\n}`,\n protected: `import { ProtectedRoute } from '@/components/Auth';\n\nfunction AdminPanel() {\n return (\n <ProtectedRoute requiredRole=\"admin\">\n <div>Admin-only content</div>\n </ProtectedRoute>\n );\n}`,\n};\n\n/**\n * AuthShowcase component demonstrating all authentication features\n */\nexport const AuthShowcase: React.FC = () => {\n const [activeTab, setActiveTab] = useState('demo');\n const [authMode, setAuthMode] = useState<'login' | 'signup'>('login');\n\n const copyToClipboard = async (code: string) => {\n try {\n await navigator.clipboard.writeText(code);\n showToast.success('Code copied to clipboard!');\n } catch (err) {\n showToast.error('Failed to copy code');\n }\n };\n\n return (\n <AuthProvider>\n <div className=\"space-y-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-gray-900\">Authentication Components</h1>\n <p className=\"text-gray-600 mt-1\">\n Comprehensive authentication system with forms, validation, and protection\n </p>\n </div>\n <Badge variant=\"outline\" className=\"flex items-center\">\n <Shield className=\"h-4 w-4 mr-1\" />\n Secure\n </Badge>\n </div>\n\n {/* Tabs */}\n <Tabs value={activeTab} onValueChange={setActiveTab}>\n <TabsList>\n <TabsTrigger value=\"demo\">\n <Eye className=\"h-4 w-4 mr-2\" />\n Demo\n </TabsTrigger>\n <TabsTrigger value=\"code\">\n <Code className=\"h-4 w-4 mr-2\" />\n Code Examples\n </TabsTrigger>\n <TabsTrigger value=\"features\">\n <Settings className=\"h-4 w-4 mr-2\" />\n Features\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"demo\" className=\"mt-6\">\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n {/* Authentication Forms */}\n <div>\n <Card>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle>Authentication Forms</CardTitle>\n <div className=\"flex bg-gray-100 rounded-lg p-1\">\n <Button\n variant={authMode === 'login' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setAuthMode('login')}\n >\n <Lock className=\"h-4 w-4 mr-1\" />\n Login\n </Button>\n <Button\n variant={authMode === 'signup' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => setAuthMode('signup')}\n >\n <UserPlus className=\"h-4 w-4 mr-1\" />\n Signup\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n {authMode === 'login' ? (\n <LoginForm\n onSuccess={() => showToast.success('Login successful!')}\n onForgotPassword={() => showToast.info('Forgot password clicked')}\n onSignupClick={() => setAuthMode('signup')}\n />\n ) : (\n <SignupForm\n onSuccess={() => showToast.success('Signup successful!')}\n onLoginClick={() => setAuthMode('login')}\n />\n )}\n </CardContent>\n </Card>\n </div>\n\n {/* Authentication Status */}\n <div>\n <AuthStatus />\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"code\" className=\"mt-6\">\n <div className=\"space-y-6\">\n {Object.entries(codeExamples).map(([key, code]) => (\n <Card key={key}>\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <CardTitle className=\"capitalize\">{key} Example</CardTitle>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => copyToClipboard(code)}\n >\n Copy Code\n </Button>\n </CardHeader>\n <CardContent>\n <pre className=\"bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm\">\n <code>{code}</code>\n </pre>\n </CardContent>\n </Card>\n ))}\n </div>\n </TabsContent>\n\n <TabsContent value=\"features\" className=\"mt-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <Card>\n <CardHeader>\n <CardTitle>LoginForm Features</CardTitle>\n </CardHeader>\n <CardContent>\n <ul className=\"space-y-2 text-sm text-gray-600\">\n <li>• Email/password validation with Zod schema</li>\n <li>• Password visibility toggle</li>\n <li>• \"Remember me\" functionality</li>\n <li>• Loading states and error handling</li>\n <li>• ARIA labels for accessibility</li>\n <li>• Keyboard navigation support</li>\n <li>• Demo credentials provided</li>\n </ul>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>SignupForm Features</CardTitle>\n </CardHeader>\n <CardContent>\n <ul className=\"space-y-2 text-sm text-gray-600\">\n <li>• Real-time form validation</li>\n <li>• Password strength indicator</li>\n <li>• Password confirmation matching</li>\n <li>• Terms of service acceptance</li>\n <li>• Email uniqueness validation</li>\n <li>• Responsive design</li>\n <li>• Error boundary protection</li>\n </ul>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>AuthProvider Features</CardTitle>\n </CardHeader>\n <CardContent>\n <ul className=\"space-y-2 text-sm text-gray-600\">\n <li>• Context-based state management</li>\n <li>• Token persistence with cookies</li>\n <li>• Automatic token refresh</li>\n <li>• Session management</li>\n <li>• Error handling and recovery</li>\n <li>• TypeScript support</li>\n <li>• Secure cookie configuration</li>\n </ul>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>ProtectedRoute Features</CardTitle>\n </CardHeader>\n <CardContent>\n <ul className=\"space-y-2 text-sm text-gray-600\">\n <li>• Authentication checking</li>\n <li>• Role-based access control</li>\n <li>• Automatic redirects</li>\n <li>• Loading states</li>\n <li>• Custom fallback components</li>\n <li>• Location state preservation</li>\n <li>• HOC pattern support</li>\n </ul>\n </CardContent>\n </Card>\n </div>\n </TabsContent>\n </Tabs>\n </div>\n </AuthProvider>\n );\n};"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface LoginFormProps {
|
|
3
|
+
className?: string;
|
|
4
|
+
onSuccess?: () => void;
|
|
5
|
+
onForgotPassword?: () => void;
|
|
6
|
+
onSignupClick?: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* LoginForm component with validation and accessibility features
|
|
10
|
+
*/
|
|
11
|
+
export declare const LoginForm: React.FC<LoginFormProps>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { LoginForm } from './LoginForm.js';
|
|
3
|
+
import { Card, CardHeader, CardTitle, CardContent } from '../Card/Card.js';
|
|
4
|
+
import { AuthProvider } from '../../contexts/AuthContext.js';
|
|
5
|
+
|
|
6
|
+
const LoginFormExample = () => (jsx(AuthProvider, { children: jsx("div", { className: "flex items-center justify-center min-h-[400px] bg-background", children: jsxs(Card, { className: "w-full max-w-md", children: [jsx(CardHeader, { children: jsx(CardTitle, { children: "Login" }) }), jsx(CardContent, { children: jsx(LoginForm, {}) })] }) }) }));
|
|
7
|
+
|
|
8
|
+
export { LoginFormExample };
|
|
9
|
+
//# sourceMappingURL=LoginForm.example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginForm.example.js","sources":["../../../src/components/Auth/LoginForm.example.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport { LoginForm } from \"./LoginForm\";\r\nimport { Card, CardHeader, CardTitle, CardContent } from \"../Card\";\r\nimport { AuthProvider } from \"../../contexts/AuthContext\";\r\n\r\nexport const LoginFormExample: React.FC = () => (\r\n <AuthProvider>\r\n <div className=\"flex items-center justify-center min-h-[400px] bg-background\">\r\n <Card className=\"w-full max-w-md\">\r\n <CardHeader>\r\n <CardTitle>Login</CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <LoginForm />\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </AuthProvider>\r\n);"],"names":["_jsx","_jsxs"],"mappings":";;;;;AAKO,MAAM,gBAAgB,GAAa,OACxCA,GAAA,CAAC,YAAY,EAAA,EAAA,QAAA,EACXA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,8DAA8D,YAC3EC,IAAA,CAAC,IAAI,IAAC,SAAS,EAAC,iBAAiB,EAAA,QAAA,EAAA,CAC/BD,IAAC,UAAU,EAAA,EAAA,QAAA,EACTA,IAAC,SAAS,EAAA,EAAA,QAAA,EAAA,OAAA,EAAA,CAAkB,GACjB,EACbA,GAAA,CAAC,WAAW,EAAA,EAAA,QAAA,EACVA,GAAA,CAAC,SAAS,EAAA,EAAA,CAAG,EAAA,CACD,IACT,EAAA,CACH,EAAA,CACO;;;;"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { useForm } from '../../node_modules/react-hook-form/dist/index.esm.js';
|
|
4
|
+
import { zodResolver as a } from '../../node_modules/@hookform/resolvers/zod/dist/zod.js';
|
|
5
|
+
import { AlertCircle, Mail, Lock, EyeOff, Eye } from 'lucide-react';
|
|
6
|
+
import { cn } from '../../utils/cn.js';
|
|
7
|
+
import { Button } from '../Button/Button.js';
|
|
8
|
+
import { Input } from '../Input/Input.js';
|
|
9
|
+
import { Checkbox } from '../Checkbox/Checkbox.js';
|
|
10
|
+
import { Alert, AlertDescription } from '../Alert/Alert.js';
|
|
11
|
+
import { Spinner } from '../Spinner/Spinner.js';
|
|
12
|
+
import { useAuth } from '../../contexts/AuthContext.js';
|
|
13
|
+
import { loginSchema } from '../../utils/validation.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* LoginForm component with validation and accessibility features
|
|
17
|
+
*/
|
|
18
|
+
const LoginForm = ({ className, onSuccess, onForgotPassword, onSignupClick, }) => {
|
|
19
|
+
const { login, isLoading, error, clearError } = useAuth();
|
|
20
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
21
|
+
const { register, handleSubmit, formState: { errors, isSubmitting }, reset, } = useForm({
|
|
22
|
+
resolver: a(loginSchema),
|
|
23
|
+
defaultValues: {
|
|
24
|
+
email: '',
|
|
25
|
+
password: '',
|
|
26
|
+
rememberMe: false,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
const onSubmit = async (data) => {
|
|
30
|
+
try {
|
|
31
|
+
clearError();
|
|
32
|
+
await login(data);
|
|
33
|
+
reset();
|
|
34
|
+
onSuccess?.();
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
// Error is handled by the auth context
|
|
38
|
+
console.error('Login failed:', error);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const togglePasswordVisibility = () => {
|
|
42
|
+
setShowPassword(prev => !prev);
|
|
43
|
+
};
|
|
44
|
+
return (jsx("div", { className: cn('w-full max-w-md mx-auto', className), children: jsxs("div", { className: "bg-white rounded-lg shadow-lg p-8", children: [jsxs("div", { className: "text-center mb-8", children: [jsx("h1", { className: "text-2xl font-bold text-gray-900 mb-2", children: "Welcome Back" }), jsx("p", { className: "text-gray-600", children: "Sign in to your account to continue" })] }), error && (jsxs(Alert, { variant: "danger", className: "mb-6", children: [jsx(AlertCircle, { className: "h-4 w-4" }), jsx(AlertDescription, { children: error })] })), jsxs("form", { onSubmit: handleSubmit(onSubmit), className: "space-y-6", children: [jsxs("div", { children: [jsx("label", { htmlFor: "email", className: "block text-sm font-medium text-gray-700 mb-2", children: "Email Address" }), jsxs("div", { className: "relative", children: [jsx(Mail, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400" }), jsx(Input, { id: "email", type: "email", placeholder: "Enter your email", className: cn('pl-10', errors.email && 'border-danger-500 focus:ring-danger-500'), "aria-invalid": errors.email ? 'true' : 'false', "aria-describedby": errors.email ? 'email-error' : undefined, ...register('email') })] }), errors.email && (jsx("p", { id: "email-error", className: "mt-1 text-sm text-danger-600", role: "alert", children: errors.email.message }))] }), jsxs("div", { children: [jsx("label", { htmlFor: "password", className: "block text-sm font-medium text-gray-700 mb-2", children: "Password" }), jsxs("div", { className: "relative", children: [jsx(Lock, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400" }), jsx(Input, { id: "password", type: showPassword ? 'text' : 'password', placeholder: "Enter your password", className: cn('pl-10 pr-10', errors.password && 'border-danger-500 focus:ring-danger-500'), "aria-invalid": errors.password ? 'true' : 'false', "aria-describedby": errors.password ? 'password-error' : undefined, ...register('password') }), jsx("button", { type: "button", onClick: togglePasswordVisibility, className: "absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600", "aria-label": showPassword ? 'Hide password' : 'Show password', children: showPassword ? (jsx(EyeOff, { className: "h-5 w-5" })) : (jsx(Eye, { className: "h-5 w-5" })) })] }), errors.password && (jsx("p", { id: "password-error", className: "mt-1 text-sm text-danger-600", role: "alert", children: errors.password.message }))] }), jsxs("div", { className: "flex items-center justify-between", children: [jsxs("label", { className: "flex items-center", children: [jsx(Checkbox, { ...register('rememberMe') }), jsx("span", { className: "ml-2 text-sm text-gray-600", children: "Remember me" })] }), jsx("button", { type: "button", onClick: onForgotPassword, className: "text-sm text-primary-600 hover:text-primary-500 font-medium", children: "Forgot password?" })] }), jsx(Button, { type: "submit", variant: "primary", className: "w-full", disabled: isSubmitting || isLoading, children: isSubmitting || isLoading ? (jsxs(Fragment, { children: [jsx(Spinner, { size: "sm", className: "mr-2" }), "Signing in..."] })) : ('Sign In') })] }), jsxs("div", { className: "mt-6 p-4 bg-gray-50 rounded-lg", children: [jsx("p", { className: "text-sm text-gray-600 mb-2 font-medium", children: "Demo Credentials:" }), jsxs("p", { className: "text-xs text-gray-500", children: ["Email: admin@example.com", jsx("br", {}), "Password: Password123!"] })] }), jsx("div", { className: "mt-6 text-center", children: jsxs("p", { className: "text-sm text-gray-600", children: ["Don't have an account?", ' ', jsx("button", { type: "button", onClick: onSignupClick, className: "text-primary-600 hover:text-primary-500 font-medium", children: "Sign up" })] }) })] }) }));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { LoginForm };
|
|
48
|
+
//# sourceMappingURL=LoginForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoginForm.js","sources":["../../../src/components/Auth/LoginForm.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Eye, EyeOff, Mail, Lock, AlertCircle } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Button } from '../Button';\nimport { Input } from '../Input';\nimport { Checkbox } from '../Checkbox';\nimport { Alert, AlertDescription } from '../Alert';\nimport { Spinner } from '../Spinner';\nimport { useAuth } from '../../contexts/AuthContext';\nimport { loginSchema, type LoginFormData } from '../../utils/validation';\n\ninterface LoginFormProps {\n className?: string;\n onSuccess?: () => void;\n onForgotPassword?: () => void;\n onSignupClick?: () => void;\n}\n\n/**\n * LoginForm component with validation and accessibility features\n */\nexport const LoginForm: React.FC<LoginFormProps> = ({\n className,\n onSuccess,\n onForgotPassword,\n onSignupClick,\n}) => {\n const { login, isLoading, error, clearError } = useAuth();\n const [showPassword, setShowPassword] = useState(false);\n\n const {\n register,\n handleSubmit,\n formState: { errors, isSubmitting },\n reset,\n } = useForm<LoginFormData>({\n resolver: zodResolver(loginSchema),\n defaultValues: {\n email: '',\n password: '',\n rememberMe: false,\n },\n });\n\n const onSubmit = async (data: LoginFormData) => {\n try {\n clearError();\n await login(data);\n reset();\n onSuccess?.();\n } catch (error) {\n // Error is handled by the auth context\n console.error('Login failed:', error);\n }\n };\n\n const togglePasswordVisibility = () => {\n setShowPassword(prev => !prev);\n };\n\n return (\n <div className={cn('w-full max-w-md mx-auto', className)}>\n <div className=\"bg-white rounded-lg shadow-lg p-8\">\n {/* Header */}\n <div className=\"text-center mb-8\">\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2\">\n Welcome Back\n </h1>\n <p className=\"text-gray-600\">\n Sign in to your account to continue\n </p>\n </div>\n\n {/* Error Alert */}\n {error && (\n <Alert variant=\"danger\" className=\"mb-6\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n {/* Login Form */}\n <form onSubmit={handleSubmit(onSubmit)} className=\"space-y-6\">\n {/* Email Field */}\n <div>\n <label\n htmlFor=\"email\"\n className=\"block text-sm font-medium text-gray-700 mb-2\"\n >\n Email Address\n </label>\n <div className=\"relative\">\n <Mail className=\"absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400\" />\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"Enter your email\"\n className={cn(\n 'pl-10',\n errors.email && 'border-danger-500 focus:ring-danger-500'\n )}\n aria-invalid={errors.email ? 'true' : 'false'}\n aria-describedby={errors.email ? 'email-error' : undefined}\n {...register('email')}\n />\n </div>\n {errors.email && (\n <p\n id=\"email-error\"\n className=\"mt-1 text-sm text-danger-600\"\n role=\"alert\"\n >\n {errors.email.message}\n </p>\n )}\n </div>\n\n {/* Password Field */}\n <div>\n <label\n htmlFor=\"password\"\n className=\"block text-sm font-medium text-gray-700 mb-2\"\n >\n Password\n </label>\n <div className=\"relative\">\n <Lock className=\"absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400\" />\n <Input\n id=\"password\"\n type={showPassword ? 'text' : 'password'}\n placeholder=\"Enter your password\"\n className={cn(\n 'pl-10 pr-10',\n errors.password && 'border-danger-500 focus:ring-danger-500'\n )}\n aria-invalid={errors.password ? 'true' : 'false'}\n aria-describedby={errors.password ? 'password-error' : undefined}\n {...register('password')}\n />\n <button\n type=\"button\"\n onClick={togglePasswordVisibility}\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600\"\n aria-label={showPassword ? 'Hide password' : 'Show password'}\n >\n {showPassword ? (\n <EyeOff className=\"h-5 w-5\" />\n ) : (\n <Eye className=\"h-5 w-5\" />\n )}\n </button>\n </div>\n {errors.password && (\n <p\n id=\"password-error\"\n className=\"mt-1 text-sm text-danger-600\"\n role=\"alert\"\n >\n {errors.password.message}\n </p>\n )}\n </div>\n\n {/* Remember Me & Forgot Password */}\n <div className=\"flex items-center justify-between\">\n <label className=\"flex items-center\">\n <Checkbox {...register('rememberMe')} />\n <span className=\"ml-2 text-sm text-gray-600\">Remember me</span>\n </label>\n <button\n type=\"button\"\n onClick={onForgotPassword}\n className=\"text-sm text-primary-600 hover:text-primary-500 font-medium\"\n >\n Forgot password?\n </button>\n </div>\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n variant=\"primary\"\n className=\"w-full\"\n disabled={isSubmitting || isLoading}\n >\n {isSubmitting || isLoading ? (\n <>\n <Spinner size=\"sm\" className=\"mr-2\" />\n Signing in...\n </>\n ) : (\n 'Sign In'\n )}\n </Button>\n </form>\n\n {/* Demo Credentials */}\n <div className=\"mt-6 p-4 bg-gray-50 rounded-lg\">\n <p className=\"text-sm text-gray-600 mb-2 font-medium\">Demo Credentials:</p>\n <p className=\"text-xs text-gray-500\">\n Email: admin@example.com<br />\n Password: Password123!\n </p>\n </div>\n\n {/* Sign Up Link */}\n <div className=\"mt-6 text-center\">\n <p className=\"text-sm text-gray-600\">\n Don't have an account?{' '}\n <button\n type=\"button\"\n onClick={onSignupClick}\n className=\"text-primary-600 hover:text-primary-500 font-medium\"\n >\n Sign up\n </button>\n </p>\n </div>\n </div>\n </div>\n );\n};"],"names":["zodResolver","_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface PasswordResetFormProps {
|
|
3
|
+
onReset?: (email: string) => Promise<void> | void;
|
|
4
|
+
className?: string;
|
|
5
|
+
isLoading?: boolean;
|
|
6
|
+
successMessage?: string;
|
|
7
|
+
errorMessage?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const PasswordResetForm: React.FC<PasswordResetFormProps>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { PasswordResetForm } from './PasswordResetForm.js';
|
|
4
|
+
import { Card, CardHeader, CardTitle, CardContent } from '../Card/Card.js';
|
|
5
|
+
import { toast } from 'react-hot-toast';
|
|
6
|
+
|
|
7
|
+
const PasswordResetFormExample = () => {
|
|
8
|
+
const [loading, setLoading] = React.useState(false);
|
|
9
|
+
// Simulate async reset logic
|
|
10
|
+
const handleReset = async (email) => {
|
|
11
|
+
setLoading(true);
|
|
12
|
+
await new Promise((res) => setTimeout(res, 1300));
|
|
13
|
+
setLoading(false);
|
|
14
|
+
toast.success(`If an account exists for ${email}, a reset link was sent.`);
|
|
15
|
+
};
|
|
16
|
+
return (jsx("div", { className: "flex items-center justify-center min-h-[400px] bg-background", children: jsxs(Card, { className: "w-full max-w-md", children: [jsx(CardHeader, { children: jsx(CardTitle, { children: "Password Reset" }) }), jsx(CardContent, { children: jsx(PasswordResetForm, { onReset: handleReset, isLoading: loading }) })] }) }));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { PasswordResetFormExample };
|
|
20
|
+
//# sourceMappingURL=PasswordResetForm.example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordResetForm.example.js","sources":["../../../src/components/Auth/PasswordResetForm.example.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport { PasswordResetForm } from \"./PasswordResetForm\";\r\nimport { Card, CardHeader, CardTitle, CardContent } from \"../Card\";\r\nimport { toast } from \"react-hot-toast\";\r\n\r\nexport const PasswordResetFormExample: React.FC = () => {\r\n const [loading, setLoading] = React.useState(false);\r\n\r\n // Simulate async reset logic\r\n const handleReset = async (email: string) => {\r\n setLoading(true);\r\n await new Promise((res) => setTimeout(res, 1300));\r\n setLoading(false);\r\n toast.success(`If an account exists for ${email}, a reset link was sent.`);\r\n };\r\n\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px] bg-background\">\r\n <Card className=\"w-full max-w-md\">\r\n <CardHeader>\r\n <CardTitle>Password Reset</CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <PasswordResetForm\r\n onReset={handleReset}\r\n isLoading={loading}\r\n />\r\n </CardContent>\r\n </Card>\r\n </div>\r\n );\r\n};"],"names":["_jsx","_jsxs"],"mappings":";;;;;;AAKO,MAAM,wBAAwB,GAAa,MAAK;AACrD,IAAA,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;;AAGnD,IAAA,MAAM,WAAW,GAAG,OAAO,KAAa,KAAI;QAC1C,UAAU,CAAC,IAAI,CAAC;AAChB,QAAA,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjD,UAAU,CAAC,KAAK,CAAC;AACjB,QAAA,KAAK,CAAC,OAAO,CAAC,4BAA4B,KAAK,CAAA,wBAAA,CAA0B,CAAC;AAC5E,IAAA,CAAC;AAED,IAAA,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,8DAA8D,YAC3EC,IAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,iBAAiB,EAAA,QAAA,EAAA,CAC/BD,IAAC,UAAU,EAAA,EAAA,QAAA,EACTA,IAAC,SAAS,EAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,CAA2B,EAAA,CAC1B,EACbA,IAAC,WAAW,EAAA,EAAA,QAAA,EACVA,IAAC,iBAAiB,EAAA,EAChB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,OAAO,EAAA,CAClB,GACU,CAAA,EAAA,CACT,EAAA,CACH;AAEV;;;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useForm } from '../../node_modules/react-hook-form/dist/index.esm.js';
|
|
4
|
+
import { zodResolver as a } from '../../node_modules/@hookform/resolvers/zod/dist/zod.js';
|
|
5
|
+
import { Input } from '../Input/Input.js';
|
|
6
|
+
import { Button } from '../Button/Button.js';
|
|
7
|
+
import { cn } from '../../utils/cn.js';
|
|
8
|
+
import { object, string } from '../../node_modules/zod/v4/classic/schemas.js';
|
|
9
|
+
|
|
10
|
+
const schema = object({
|
|
11
|
+
email: string().min(1, "Email is required").email("Enter a valid email")
|
|
12
|
+
});
|
|
13
|
+
const PasswordResetForm = ({ onReset, className, isLoading, successMessage, errorMessage }) => {
|
|
14
|
+
const { register, handleSubmit, formState: { errors, isSubmitting, isSubmitSuccessful } } = useForm({ resolver: a(schema) });
|
|
15
|
+
const [status, setStatus] = React.useState("idle");
|
|
16
|
+
const onSubmit = async (data) => {
|
|
17
|
+
setStatus("idle");
|
|
18
|
+
try {
|
|
19
|
+
await onReset?.(data.email);
|
|
20
|
+
setStatus("success");
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
setStatus("error");
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
return (jsxs("form", { onSubmit: handleSubmit(onSubmit), className: cn("space-y-6", className), autoComplete: "off", noValidate: true, children: [jsxs("div", { children: [jsx("label", { className: "block text-sm font-medium mb-1", htmlFor: "reset-email", children: "Email Address" }), jsx(Input, { id: "reset-email", type: "email", autoComplete: "email", placeholder: "you@email.com", ...register("email"), disabled: isSubmitting || isLoading, variant: errors.email ? "error" : "default" }), errors.email && (jsx("div", { className: "text-danger mt-1 text-xs", children: errors.email.message }))] }), jsx(Button, { type: "submit", variant: "primary", disabled: isSubmitting || isLoading, className: "w-full", children: "Send Password Reset Link" }), status === "success" && (jsx("div", { className: "text-success-700 bg-success-50 border border-success-200 p-2 text-sm rounded text-center", children: successMessage || "A password reset link was sent if the address exists in our system." })), status === "error" && (jsx("div", { className: "text-danger-700 bg-danger-50 border border-danger-200 p-2 text-sm rounded text-center", children: errorMessage || "There was an error submitting. Please try again." }))] }));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { PasswordResetForm };
|
|
30
|
+
//# sourceMappingURL=PasswordResetForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordResetForm.js","sources":["../../../src/components/Auth/PasswordResetForm.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport { useForm } from \"react-hook-form\";\r\nimport { zodResolver } from \"@hookform/resolvers/zod\";\r\nimport { z } from \"zod\";\r\nimport { Input } from \"../Input\";\r\nimport { Button } from \"../Button\";\r\nimport { cn } from \"../../utils/cn\";\r\n\r\nconst schema = z.object({\r\n email: z.string().min(1, \"Email is required\").email(\"Enter a valid email\")\r\n});\r\n\r\ntype PasswordResetFormData = z.infer<typeof schema>;\r\n\r\nexport interface PasswordResetFormProps {\r\n onReset?: (email: string) => Promise<void> | void;\r\n className?: string;\r\n isLoading?: boolean;\r\n successMessage?: string;\r\n errorMessage?: string;\r\n}\r\n\r\nexport const PasswordResetForm: React.FC<PasswordResetFormProps> = ({\r\n onReset,\r\n className,\r\n isLoading,\r\n successMessage,\r\n errorMessage\r\n}) => {\r\n const {\r\n register,\r\n handleSubmit,\r\n formState: { errors, isSubmitting, isSubmitSuccessful }\r\n } = useForm<PasswordResetFormData>({ resolver: zodResolver(schema) });\r\n\r\n const [status, setStatus] = React.useState<\"idle\" | \"success\" | \"error\">(\"idle\");\r\n\r\n const onSubmit = async (data: PasswordResetFormData) => {\r\n setStatus(\"idle\");\r\n try {\r\n await onReset?.(data.email);\r\n setStatus(\"success\");\r\n } catch (e) {\r\n setStatus(\"error\");\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={handleSubmit(onSubmit)}\r\n className={cn(\"space-y-6\", className)}\r\n autoComplete=\"off\"\r\n noValidate\r\n >\r\n <div>\r\n <label className=\"block text-sm font-medium mb-1\" htmlFor=\"reset-email\">\r\n Email Address\r\n </label>\r\n <Input\r\n id=\"reset-email\"\r\n type=\"email\"\r\n autoComplete=\"email\"\r\n placeholder=\"you@email.com\"\r\n {...register(\"email\")}\r\n disabled={isSubmitting || isLoading}\r\n variant={errors.email ? \"error\" : \"default\"}\r\n />\r\n {errors.email && (\r\n <div className=\"text-danger mt-1 text-xs\">{errors.email.message}</div>\r\n )}\r\n </div>\r\n <Button\r\n type=\"submit\"\r\n variant=\"primary\"\r\n disabled={isSubmitting || isLoading}\r\n className=\"w-full\"\r\n >\r\n Send Password Reset Link\r\n </Button>\r\n {status === \"success\" && (\r\n <div className=\"text-success-700 bg-success-50 border border-success-200 p-2 text-sm rounded text-center\">\r\n {successMessage || \"A password reset link was sent if the address exists in our system.\"}\r\n </div>\r\n )}\r\n {status === \"error\" && (\r\n <div className=\"text-danger-700 bg-danger-50 border border-danger-200 p-2 text-sm rounded text-center\">\r\n {errorMessage || \"There was an error submitting. Please try again.\"}\r\n </div>\r\n )}\r\n </form>\r\n );\r\n};"],"names":["z.object","z.string","zodResolver","_jsxs","_jsx"],"mappings":";;;;;;;;;AAQA,MAAM,MAAM,GAAGA,MAAQ,CAAC;AACtB,IAAA,KAAK,EAAEC,MAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,KAAK,CAAC,qBAAqB;AAC1E,CAAA,CAAC;AAYK,MAAM,iBAAiB,GAAqC,CAAC,EAClE,OAAO,EACP,SAAS,EACT,SAAS,EACT,cAAc,EACd,YAAY,EACb,KAAI;IACH,MAAM,EACJ,QAAQ,EACR,YAAY,EACZ,SAAS,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,kBAAkB,EAAE,EACxD,GAAG,OAAO,CAAwB,EAAE,QAAQ,EAAEC,CAAW,CAAC,MAAM,CAAC,EAAE,CAAC;AAErE,IAAA,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAA+B,MAAM,CAAC;AAEhF,IAAA,MAAM,QAAQ,GAAG,OAAO,IAA2B,KAAI;QACrD,SAAS,CAAC,MAAM,CAAC;AACjB,QAAA,IAAI;AACF,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;YAC3B,SAAS,CAAC,SAAS,CAAC;QACtB;QAAE,OAAO,CAAC,EAAE;YACV,SAAS,CAAC,OAAO,CAAC;QACpB;AACF,IAAA,CAAC;AAED,IAAA,QACEC,IAAA,CAAA,MAAA,EAAA,EACE,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,EAChC,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,EACrC,YAAY,EAAC,KAAK,EAClB,UAAU,EAAA,IAAA,EAAA,QAAA,EAAA,CAEVA,yBACEC,GAAA,CAAA,OAAA,EAAA,EAAO,SAAS,EAAC,gCAAgC,EAAC,OAAO,EAAC,aAAa,EAAA,QAAA,EAAA,eAAA,EAAA,CAE/D,EACRA,GAAA,CAAC,KAAK,EAAA,EACJ,EAAE,EAAC,aAAa,EAChB,IAAI,EAAC,OAAO,EACZ,YAAY,EAAC,OAAO,EACpB,WAAW,EAAC,eAAe,EAAA,GACvB,QAAQ,CAAC,OAAO,CAAC,EACrB,QAAQ,EAAE,YAAY,IAAI,SAAS,EACnC,OAAO,EAAE,MAAM,CAAC,KAAK,GAAG,OAAO,GAAG,SAAS,EAAA,CAC3C,EACD,MAAM,CAAC,KAAK,KACXA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,0BAA0B,EAAA,QAAA,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAA,CAAO,CACvE,CAAA,EAAA,CACG,EACNA,GAAA,CAAC,MAAM,EAAA,EACL,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,SAAS,EACjB,QAAQ,EAAE,YAAY,IAAI,SAAS,EACnC,SAAS,EAAC,QAAQ,EAAA,QAAA,EAAA,0BAAA,EAAA,CAGX,EACR,MAAM,KAAK,SAAS,KACnBA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,0FAA0F,EAAA,QAAA,EACtG,cAAc,IAAI,qEAAqE,EAAA,CACpF,CACP,EACA,MAAM,KAAK,OAAO,KACjBA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,uFAAuF,EAAA,QAAA,EACnG,YAAY,IAAI,kDAAkD,EAAA,CAC/D,CACP,CAAA,EAAA,CACI;AAEX;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ProtectedRouteProps } from '../../types/auth';
|
|
3
|
+
/**
|
|
4
|
+
* ProtectedRoute component that handles authentication and role-based access control
|
|
5
|
+
*/
|
|
6
|
+
export declare const ProtectedRoute: React.FC<ProtectedRouteProps>;
|
|
7
|
+
/**
|
|
8
|
+
* Hook to check if user has required role
|
|
9
|
+
*/
|
|
10
|
+
export declare const useRequireRole: (requiredRole: string) => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Higher-order component for role-based access control
|
|
13
|
+
*/
|
|
14
|
+
export declare const withRoleProtection: <P extends object>(Component: React.ComponentType<P>, requiredRole: string, fallback?: React.ReactNode) => (props: P) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Simple demo: toggling a boolean to represent authenticated/unauthenticated.
|
|
4
|
+
* This does NOT call login/logout to avoid backend/service dependencies,
|
|
5
|
+
* and simply shows protected content or a message.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ProtectedRouteExample: React.FC;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Button } from '../Button/Button.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Simple demo: toggling a boolean to represent authenticated/unauthenticated.
|
|
7
|
+
* This does NOT call login/logout to avoid backend/service dependencies,
|
|
8
|
+
* and simply shows protected content or a message.
|
|
9
|
+
*/
|
|
10
|
+
const ProtectedRouteExample = () => {
|
|
11
|
+
const [authed, setAuthed] = React.useState(false);
|
|
12
|
+
return (jsxs("div", { className: "flex flex-col items-center gap-4 p-8 border rounded bg-background max-w-md mx-auto min-h-[200px]", children: [jsx("div", { children: jsx(Button, { onClick: () => setAuthed((prev) => !prev), children: authed ? "Logout" : "Login (Preview)" }) }), authed ? (jsx("div", { className: "p-4 text-success-700 bg-success-50 border border-success-200 rounded", children: "This content is only visible if authenticated!" })) : (jsx("div", { className: "p-4 text-danger-700 bg-danger-50 border border-danger-200 rounded", children: "You must be logged in to view protected content." }))] }));
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { ProtectedRouteExample };
|
|
16
|
+
//# sourceMappingURL=ProtectedRoute.example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProtectedRoute.example.js","sources":["../../../src/components/Auth/ProtectedRoute.example.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport { Button } from \"../Button\";\r\n\r\n/**\r\n * Simple demo: toggling a boolean to represent authenticated/unauthenticated.\r\n * This does NOT call login/logout to avoid backend/service dependencies,\r\n * and simply shows protected content or a message.\r\n */\r\nexport const ProtectedRouteExample: React.FC = () => {\r\n const [authed, setAuthed] = React.useState(false);\r\n\r\n return (\r\n <div className=\"flex flex-col items-center gap-4 p-8 border rounded bg-background max-w-md mx-auto min-h-[200px]\">\r\n <div>\r\n <Button onClick={() => setAuthed((prev) => !prev)}>\r\n {authed ? \"Logout\" : \"Login (Preview)\"}\r\n </Button>\r\n </div>\r\n {authed ? (\r\n <div className=\"p-4 text-success-700 bg-success-50 border border-success-200 rounded\">\r\n This content is only visible if authenticated!\r\n </div>\r\n ) : (\r\n <div className=\"p-4 text-danger-700 bg-danger-50 border border-danger-200 rounded\">\r\n You must be logged in to view protected content.\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};"],"names":["_jsxs","_jsx"],"mappings":";;;;AAGA;;;;AAIG;AACI,MAAM,qBAAqB,GAAa,MAAK;AAClD,IAAA,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;AAEjD,IAAA,QACEA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,kGAAkG,EAAA,QAAA,EAAA,CAC/GC,GAAA,CAAA,KAAA,EAAA,EAAA,QAAA,EACEA,GAAA,CAAC,MAAM,EAAA,EAAC,OAAO,EAAE,MAAM,SAAS,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAA,QAAA,EAC9C,MAAM,GAAG,QAAQ,GAAG,iBAAiB,EAAA,CAC/B,EAAA,CACL,EACL,MAAM,IACLA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,sEAAsE,EAAA,QAAA,EAAA,gDAAA,EAAA,CAE/E,KAENA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mEAAmE,EAAA,QAAA,EAAA,kDAAA,EAAA,CAE5E,CACP,CAAA,EAAA,CACG;AAEV;;;;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useAuth } from '../../contexts/AuthContext.js';
|
|
3
|
+
import { Spinner } from '../Spinner/Spinner.js';
|
|
4
|
+
import { useLocation, Navigate } from '../../node_modules/react-router/dist/development/chunk-B7RQU5TL.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ProtectedRoute component that handles authentication and role-based access control
|
|
8
|
+
*/
|
|
9
|
+
const ProtectedRoute = ({ children, requiredRole, fallback, redirectTo = '/login', }) => {
|
|
10
|
+
const { user, isAuthenticated, isLoading } = useAuth();
|
|
11
|
+
const location = useLocation();
|
|
12
|
+
// Show loading spinner while checking authentication
|
|
13
|
+
if (isLoading) {
|
|
14
|
+
return (jsx("div", { className: "flex items-center justify-center min-h-screen", children: jsxs("div", { className: "text-center", children: [jsx(Spinner, { size: "lg", className: "mb-4" }), jsx("p", { className: "text-gray-600", children: "Checking authentication..." })] }) }));
|
|
15
|
+
}
|
|
16
|
+
// Redirect to login if not authenticated
|
|
17
|
+
if (!isAuthenticated || !user) {
|
|
18
|
+
return (jsx(Navigate, { to: redirectTo, state: { from: location }, replace: true }));
|
|
19
|
+
}
|
|
20
|
+
// Check role-based access if required
|
|
21
|
+
if (requiredRole && user.role !== requiredRole) {
|
|
22
|
+
// Show fallback component or redirect to unauthorized page
|
|
23
|
+
if (fallback) {
|
|
24
|
+
return jsx(Fragment, { children: fallback });
|
|
25
|
+
}
|
|
26
|
+
return (jsx("div", { className: "flex items-center justify-center min-h-screen", children: jsxs("div", { className: "text-center max-w-md mx-auto p-8", children: [jsx("div", { className: "w-16 h-16 bg-danger-100 rounded-full flex items-center justify-center mx-auto mb-4", children: jsx("svg", { className: "w-8 h-8 text-danger-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" }) }) }), jsx("h2", { className: "text-2xl font-bold text-gray-900 mb-2", children: "Access Denied" }), jsxs("p", { className: "text-gray-600 mb-6", children: ["You don't have permission to access this page. Required role: ", requiredRole] }), jsx("button", { onClick: () => window.history.back(), className: "text-primary-600 hover:text-primary-500 font-medium", children: "Go Back" })] }) }));
|
|
27
|
+
}
|
|
28
|
+
// Render protected content
|
|
29
|
+
return jsx(Fragment, { children: children });
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { ProtectedRoute };
|
|
33
|
+
//# sourceMappingURL=ProtectedRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProtectedRoute.js","sources":["../../../src/components/Auth/ProtectedRoute.tsx"],"sourcesContent":["import React from 'react';\nimport { Navigate, useLocation } from 'react-router-dom';\nimport { useAuth } from '../../contexts/AuthContext';\nimport { Spinner } from '../Spinner';\nimport type { ProtectedRouteProps } from '../../types/auth';\n\n/**\n * ProtectedRoute component that handles authentication and role-based access control\n */\nexport const ProtectedRoute: React.FC<ProtectedRouteProps> = ({\n children,\n requiredRole,\n fallback,\n redirectTo = '/login',\n}) => {\n const { user, isAuthenticated, isLoading } = useAuth();\n const location = useLocation();\n\n // Show loading spinner while checking authentication\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center min-h-screen\">\n <div className=\"text-center\">\n <Spinner size=\"lg\" className=\"mb-4\" />\n <p className=\"text-gray-600\">Checking authentication...</p>\n </div>\n </div>\n );\n }\n\n // Redirect to login if not authenticated\n if (!isAuthenticated || !user) {\n return (\n <Navigate\n to={redirectTo}\n state={{ from: location }}\n replace\n />\n );\n }\n\n // Check role-based access if required\n if (requiredRole && user.role !== requiredRole) {\n // Show fallback component or redirect to unauthorized page\n if (fallback) {\n return <>{fallback}</>;\n }\n\n return (\n <div className=\"flex items-center justify-center min-h-screen\">\n <div className=\"text-center max-w-md mx-auto p-8\">\n <div className=\"w-16 h-16 bg-danger-100 rounded-full flex items-center justify-center mx-auto mb-4\">\n <svg\n className=\"w-8 h-8 text-danger-600\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n </div>\n <h2 className=\"text-2xl font-bold text-gray-900 mb-2\">\n Access Denied\n </h2>\n <p className=\"text-gray-600 mb-6\">\n You don't have permission to access this page. Required role: {requiredRole}\n </p>\n <button\n onClick={() => window.history.back()}\n className=\"text-primary-600 hover:text-primary-500 font-medium\"\n >\n Go Back\n </button>\n </div>\n </div>\n );\n }\n\n // Render protected content\n return <>{children}</>;\n};\n\n/**\n * Hook to check if user has required role\n */\nexport const useRequireRole = (requiredRole: string): boolean => {\n const { user, isAuthenticated } = useAuth();\n return isAuthenticated && user?.role === requiredRole;\n};\n\n/**\n * Higher-order component for role-based access control\n */\nexport const withRoleProtection = <P extends object>(\n Component: React.ComponentType<P>,\n requiredRole: string,\n fallback?: React.ReactNode\n) => {\n return (props: P) => (\n <ProtectedRoute requiredRole={requiredRole as any} fallback={fallback}>\n <Component {...props} />\n </ProtectedRoute>\n );\n};"],"names":["_jsx","_jsxs","_Fragment"],"mappings":";;;;;AAMA;;AAEG;AACI,MAAM,cAAc,GAAkC,CAAC,EAC5D,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,UAAU,GAAG,QAAQ,GACtB,KAAI;IACH,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE;AACtD,IAAA,MAAM,QAAQ,GAAG,WAAW,EAAE;;IAG9B,IAAI,SAAS,EAAE;AACb,QAAA,QACEA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,+CAA+C,EAAA,QAAA,EAC5DC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,aAAa,EAAA,QAAA,EAAA,CAC1BD,GAAA,CAAC,OAAO,EAAA,EAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,MAAM,GAAG,EACtCA,GAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,eAAe,EAAA,QAAA,EAAA,4BAAA,EAAA,CAA+B,CAAA,EAAA,CACvD,EAAA,CACF;IAEV;;AAGA,IAAA,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,EAAE;AAC7B,QAAA,QACEA,GAAA,CAAC,QAAQ,IACP,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EACzB,OAAO,EAAA,IAAA,EAAA,CACP;IAEN;;IAGA,IAAI,YAAY,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE;;QAE9C,IAAI,QAAQ,EAAE;YACZ,OAAOA,GAAA,CAAAE,QAAA,EAAA,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAI;QACxB;AAEA,QAAA,QACEF,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,+CAA+C,EAAA,QAAA,EAC5DC,cAAK,SAAS,EAAC,kCAAkC,EAAA,QAAA,EAAA,CAC/CD,aAAK,SAAS,EAAC,oFAAoF,EAAA,QAAA,EACjGA,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAC,yBAAyB,EACnC,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,OAAO,EAAC,WAAW,EAAA,QAAA,EAEnBA,GAAA,CAAA,MAAA,EAAA,EACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAE,CAAC,EACd,CAAC,EAAC,2IAA2I,EAAA,CAC7I,EAAA,CACE,GACF,EACNA,GAAA,CAAA,IAAA,EAAA,EAAI,SAAS,EAAC,uCAAuC,8BAEhD,EACLC,IAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,oBAAoB,+EACgC,YAAY,CAAA,EAAA,CACzE,EACJD,GAAA,CAAA,QAAA,EAAA,EACE,OAAO,EAAE,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EACpC,SAAS,EAAC,qDAAqD,wBAGxD,CAAA,EAAA,CACL,EAAA,CACF;IAEV;;IAGA,OAAOA,GAAA,CAAAE,QAAA,EAAA,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAI;AACxB;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface SignupFormProps {
|
|
3
|
+
className?: string;
|
|
4
|
+
onSuccess?: () => void;
|
|
5
|
+
onLoginClick?: () => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* SignupForm component with real-time validation and password strength indicator
|
|
9
|
+
*/
|
|
10
|
+
export declare const SignupForm: React.FC<SignupFormProps>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { SignupForm } from './SignupForm.js';
|
|
3
|
+
import { Card, CardHeader, CardTitle, CardContent } from '../Card/Card.js';
|
|
4
|
+
import { AuthProvider } from '../../contexts/AuthContext.js';
|
|
5
|
+
|
|
6
|
+
const SignupFormExample = () => (jsx(AuthProvider, { children: jsx("div", { className: "flex items-center justify-center min-h-[400px] bg-background", children: jsxs(Card, { className: "w-full max-w-md", children: [jsx(CardHeader, { children: jsx(CardTitle, { children: "Sign Up" }) }), jsx(CardContent, { children: jsx(SignupForm, {}) })] }) }) }));
|
|
7
|
+
|
|
8
|
+
export { SignupFormExample };
|
|
9
|
+
//# sourceMappingURL=SignupForm.example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignupForm.example.js","sources":["../../../src/components/Auth/SignupForm.example.tsx"],"sourcesContent":["import * as React from \"react\";\r\nimport { SignupForm } from \"./SignupForm\";\r\nimport { Card, CardHeader, CardTitle, CardContent } from \"../Card\";\r\nimport { AuthProvider } from \"../../contexts/AuthContext\";\r\n\r\nexport const SignupFormExample: React.FC = () => (\r\n <AuthProvider>\r\n <div className=\"flex items-center justify-center min-h-[400px] bg-background\">\r\n <Card className=\"w-full max-w-md\">\r\n <CardHeader>\r\n <CardTitle>Sign Up</CardTitle>\r\n </CardHeader>\r\n <CardContent>\r\n <SignupForm />\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </AuthProvider>\r\n);"],"names":["_jsx","_jsxs"],"mappings":";;;;;AAKO,MAAM,iBAAiB,GAAa,OACzCA,GAAA,CAAC,YAAY,EAAA,EAAA,QAAA,EACXA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,8DAA8D,YAC3EC,IAAA,CAAC,IAAI,IAAC,SAAS,EAAC,iBAAiB,EAAA,QAAA,EAAA,CAC/BD,IAAC,UAAU,EAAA,EAAA,QAAA,EACTA,IAAC,SAAS,EAAA,EAAA,QAAA,EAAA,SAAA,EAAA,CAAoB,GACnB,EACbA,GAAA,CAAC,WAAW,EAAA,EAAA,QAAA,EACVA,GAAA,CAAC,UAAU,EAAA,EAAA,CAAG,EAAA,CACF,IACT,EAAA,CACH,EAAA,CACO;;;;"}
|