@kendevelops/auth-flow-kit 2.3.7 → 2.3.8
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 +115 -4
- package/dist/index.cjs +38 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +38 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,11 +23,11 @@ auth-flow-kit keeps authentication state in memory by default, and automatically
|
|
|
23
23
|
|
|
24
24
|
**What this means in practice:**
|
|
25
25
|
|
|
26
|
-
From a developer
|
|
26
|
+
From a developer's point of view:
|
|
27
27
|
|
|
28
|
-
>
|
|
28
|
+
> "I refresh the page and I'm still logged in."
|
|
29
29
|
|
|
30
|
-
That
|
|
30
|
+
That's it.
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
@@ -110,7 +110,7 @@ import { useEffect, useState } from "react";
|
|
|
110
110
|
export default function Home() {
|
|
111
111
|
const { user } = useAuth();
|
|
112
112
|
const [page, setPage] = useState<"login" | "signup" | "reset" | "dashboard">(
|
|
113
|
-
"login"
|
|
113
|
+
"login",
|
|
114
114
|
);
|
|
115
115
|
|
|
116
116
|
// Keep UI in sync with auth (important on refresh)
|
|
@@ -214,6 +214,117 @@ export default function App() {
|
|
|
214
214
|
|
|
215
215
|
---
|
|
216
216
|
|
|
217
|
+
# 🛠 Backend Requirements
|
|
218
|
+
|
|
219
|
+
This section defines the exact API contract your backend must implement. The library makes three types of requests and expects specific JSON response shapes.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## POST `/auth/login`
|
|
224
|
+
|
|
225
|
+
**Request body:**
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"email": "user@example.com",
|
|
230
|
+
"password": "secret123"
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Success response (200):**
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"accessToken": "your-token-here",
|
|
239
|
+
"user": {
|
|
240
|
+
"id": "usr_abc123",
|
|
241
|
+
"name": "Jane Doe",
|
|
242
|
+
"email": "user@example.com"
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Error response (4xx):**
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{ "message": "Invalid email or password" }
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
The `message` field is displayed directly to the user in the login form.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## POST `/auth/signup`
|
|
258
|
+
|
|
259
|
+
**Request body:**
|
|
260
|
+
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"name": "Jane Doe",
|
|
264
|
+
"email": "user@example.com",
|
|
265
|
+
"password": "secret123"
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
> You can include extra fields in your signup form and pass them through — the library forwards the full payload as-is.
|
|
270
|
+
|
|
271
|
+
**Success response (200):** Same shape as the login response.
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"accessToken": "your-token-here",
|
|
276
|
+
"user": {
|
|
277
|
+
"id": "usr_xyz789",
|
|
278
|
+
"name": "Jane Doe",
|
|
279
|
+
"email": "user@example.com"
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## POST `/auth/forgot` _(optional)_
|
|
287
|
+
|
|
288
|
+
Only needed if you use `<PasswordResetScreen />`.
|
|
289
|
+
|
|
290
|
+
**Request body:**
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
{ "email": "user@example.com" }
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Response:** Any `2xx` is treated as success. The library does not read the response body — it just shows a "Check your email" confirmation. A `404` logs a descriptive console error with guidance on fixing `config.endpoints.forgot`.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Response field reference
|
|
301
|
+
|
|
302
|
+
| Field | Type | Required | Description |
|
|
303
|
+
| -------------- | ------ | -------- | --------------------------------------------------------------------------------------------------- |
|
|
304
|
+
| `accessToken` | string | ✅ | Stored in `localStorage` and sent as `Authorization: Bearer <token>` on authenticated requests. |
|
|
305
|
+
| `user` | object | ✅ | Stored in `localStorage` and exposed via `useAuth().user`. |
|
|
306
|
+
| `user.id` | string | ✅ | Unique user identifier. |
|
|
307
|
+
| `user.name` | string | ✅ | Display name used in your UI. |
|
|
308
|
+
| `user.email` | string | ✅ | User's email address. |
|
|
309
|
+
| `refreshToken` | string | ❌ | Accepted but not used by the library for now, updating soon. You can include it for your own logic. |
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## How session persistence works
|
|
314
|
+
|
|
315
|
+
auth-flow-kit handles persistence entirely on the client — **your backend does not need a session restore or `/me` endpoint.**
|
|
316
|
+
|
|
317
|
+
On successful login or signup:
|
|
318
|
+
|
|
319
|
+
- `accessToken` is saved to `localStorage` as `afk_access_token`
|
|
320
|
+
- `user` is saved to `localStorage` as `afk_user`
|
|
321
|
+
|
|
322
|
+
On page reload, `AuthProvider` reads `afk_user` directly from `localStorage` and restores the session instantly — no network request is made.
|
|
323
|
+
|
|
324
|
+
On logout, both keys are removed.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
217
328
|
# 🎯 Who This Library Is For
|
|
218
329
|
|
|
219
330
|
- Developers who want to go straight into building their app before worrying about auth
|
package/dist/index.cjs
CHANGED
|
@@ -34,66 +34,79 @@ var import_react = require("react");
|
|
|
34
34
|
|
|
35
35
|
// src/http.ts
|
|
36
36
|
function makeURL(baseURL, path) {
|
|
37
|
-
|
|
37
|
+
const cleanedBase = baseURL.replace(/\/$/, "");
|
|
38
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
39
|
+
return `${cleanedBase}${normalizedPath}`;
|
|
38
40
|
}
|
|
39
41
|
function getStoredAccessToken() {
|
|
40
42
|
try {
|
|
41
|
-
|
|
43
|
+
const token = localStorage.getItem("afk_access_token");
|
|
44
|
+
return token;
|
|
42
45
|
} catch {
|
|
43
46
|
return null;
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
function setStoredAccessToken(token) {
|
|
47
50
|
try {
|
|
48
|
-
if (token)
|
|
49
|
-
|
|
51
|
+
if (!token) {
|
|
52
|
+
localStorage.removeItem("afk_access_token");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
localStorage.setItem("afk_access_token", token);
|
|
50
56
|
} catch {
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
59
|
async function httpJSON(url, opts = {}, withAuth = false) {
|
|
54
|
-
const
|
|
60
|
+
const baseHeaders = {
|
|
55
61
|
"Content-Type": "application/json"
|
|
56
62
|
};
|
|
57
63
|
if (withAuth) {
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
64
|
+
const token = getStoredAccessToken();
|
|
65
|
+
if (token) {
|
|
66
|
+
baseHeaders["Authorization"] = `Bearer ${token}`;
|
|
67
|
+
}
|
|
60
68
|
}
|
|
61
|
-
const
|
|
69
|
+
const response = await fetch(url, {
|
|
62
70
|
...opts,
|
|
63
|
-
headers: {
|
|
71
|
+
headers: {
|
|
72
|
+
...baseHeaders,
|
|
73
|
+
...opts.headers ?? {}
|
|
74
|
+
}
|
|
64
75
|
});
|
|
65
|
-
if (!
|
|
66
|
-
|
|
67
|
-
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
78
|
+
let errorMessage = `Request failed (${response.status})`;
|
|
68
79
|
if (contentType.includes("application/json")) {
|
|
69
80
|
try {
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
81
|
+
const payload = await response.json();
|
|
82
|
+
if (payload?.message) {
|
|
83
|
+
errorMessage = payload.message;
|
|
84
|
+
}
|
|
72
85
|
} catch {
|
|
73
86
|
}
|
|
74
87
|
}
|
|
75
88
|
if (contentType.includes("text/html")) {
|
|
76
|
-
if (
|
|
77
|
-
|
|
89
|
+
if (response.status === 404 && url.includes("forgot")) {
|
|
90
|
+
errorMessage = "The forgot password endpoint you added in config.endpoints.forgot does not exist in your server. Please check and update your config.endpoints.forgot";
|
|
78
91
|
} else {
|
|
79
|
-
|
|
92
|
+
errorMessage = "Unexpected server error";
|
|
80
93
|
}
|
|
81
94
|
}
|
|
82
|
-
if (
|
|
95
|
+
if (response.status === 404 && url.includes("forgot")) {
|
|
83
96
|
console.error(
|
|
84
97
|
`[auth-flow-kit] Password reset endpoint not found.
|
|
85
98
|
|
|
86
|
-
|
|
87
|
-
|
|
99
|
+
Expected POST route:
|
|
100
|
+
${url}
|
|
88
101
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
102
|
+
Fix by:
|
|
103
|
+
\u2022 Adding the endpoint on your backend
|
|
104
|
+
\u2022 OR updating config.endpoints.forgot`
|
|
92
105
|
);
|
|
93
106
|
}
|
|
94
|
-
throw new Error(
|
|
107
|
+
throw new Error(errorMessage);
|
|
95
108
|
}
|
|
96
|
-
return
|
|
109
|
+
return response.json();
|
|
97
110
|
}
|
|
98
111
|
|
|
99
112
|
// src/AuthContext.tsx
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/AuthContext.tsx","../src/http.ts","../src/Protected.tsx","../src/screens/LoginScreen.tsx","../src/screens/PasswordResetScreen.tsx","../src/screens/SignupScreen.tsx"],"sourcesContent":["export { AuthProvider, useAuth } from \"./AuthContext\";\r\nexport { default as Protected } from \"./Protected\";\r\n\r\n// Screens\r\nexport { default as LoginScreen } from \"./screens/LoginScreen\";\r\nexport { default as SignupScreen } from \"./screens/SignupScreen\";\r\nexport { default as PasswordResetScreen } from \"./screens/PasswordResetScreen\";\r\n\r\n// Types\r\nexport * from \"./types\";\r\n","/* \r\nDevelopers using this library should wrap their app with:\r\n <AuthProvider config={...}>\r\n <App />\r\n </AuthProvider>\r\n \r\n Then they can access auth anywhere with:\r\n const { user, login, logout, getToken } = useAuth();\r\n*/\r\n\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useState,\r\n} from \"react\";\r\n\r\nimport {\r\n AuthContextType,\r\n AuthProviderConfig,\r\n StandardAuthResponse,\r\n User,\r\n} from \"./types\";\r\n\r\nimport {\r\n httpJSON,\r\n makeURL,\r\n setStoredAccessToken,\r\n getStoredAccessToken,\r\n} from \"./http\";\r\n\r\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\r\n\r\nexport function useAuth(): AuthContextType {\r\n const ctx = useContext(AuthContext);\r\n if (!ctx) throw new Error(\"useAuth must be used inside AuthProvider\");\r\n return ctx;\r\n}\r\n\r\nexport function AuthProvider({\r\n config,\r\n children,\r\n}: React.PropsWithChildren<{ config: AuthProviderConfig }>) {\r\n const { baseURL, endpoints, onLoginSuccess, onLogout } = config;\r\n\r\n const [user, setUser] = useState<User | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n const getToken = () => getStoredAccessToken();\r\n\r\n // Restore user from localStorage on app load\r\n useEffect(() => {\r\n const savedUser = localStorage.getItem(\"afk_user\");\r\n if (savedUser) {\r\n setUser(JSON.parse(savedUser));\r\n }\r\n setLoading(false);\r\n }, []);\r\n\r\n // LOGIN\r\n const login: AuthContextType[\"login\"] = async (email, password) => {\r\n const url = makeURL(baseURL, endpoints.login);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email, password }),\r\n });\r\n\r\n // store token + user\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // SIGNUP\r\n const signup: AuthContextType[\"signup\"] = async (payload) => {\r\n const url = makeURL(baseURL, endpoints.signup);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify(payload),\r\n });\r\n\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // LOGOUT\r\n const logout = () => {\r\n setStoredAccessToken(null);\r\n localStorage.removeItem(\"afk_user\");\r\n setUser(null);\r\n\r\n if (onLogout) onLogout();\r\n };\r\n\r\n const value = useMemo<AuthContextType>(\r\n () => ({\r\n user,\r\n loading,\r\n login,\r\n signup,\r\n logout,\r\n getToken,\r\n config,\r\n }),\r\n [user, loading, config],\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n","/*\r\n This file contains the low-level HTTP utilities used internally by\r\n auth-flow-kit to communicate with the backend.\r\n\r\n It provides:\r\n - makeURL: safely joins baseURL + endpoint path\r\n - getStoredAccessToken: reads the JWT from localStorage\r\n - setStoredAccessToken: stores/removes the JWT\r\n - httpJSON: wrapper around fetch with JSON + optional auth header\r\n\r\n NOTES FOR DEVELOPERS USING THE LIBRARY:\r\n You do NOT need to import or modify anything in this file.\r\n It is an internal helper used by the AuthProvider and auth screens.\r\n\r\n This keeps the library lightweight, predictable,\r\n and familiar to developers used to Redux Toolkit-style authentication.\r\n*/\r\n\r\nexport function makeURL(baseURL: string, path: string) {\r\n return `${baseURL.replace(/\\/$/, \"\")}${\r\n path.startsWith(\"/\") ? path : `/${path}`\r\n }`;\r\n}\r\n\r\nexport function getStoredAccessToken(): string | null {\r\n try {\r\n return localStorage.getItem(\"afk_access_token\");\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function setStoredAccessToken(token: string | null) {\r\n try {\r\n if (token) localStorage.setItem(\"afk_access_token\", token);\r\n else localStorage.removeItem(\"afk_access_token\");\r\n } catch {\r\n // ignore storage errors (Safari private mode, etc.) for now, not exactly needed.\r\n }\r\n}\r\n\r\nexport async function httpJSON<T>(\r\n url: string,\r\n opts: RequestInit = {},\r\n withAuth = false,\r\n): Promise<T> {\r\n const headers: Record<string, string> = {\r\n \"Content-Type\": \"application/json\",\r\n };\r\n\r\n if (withAuth) {\r\n const tok = getStoredAccessToken();\r\n if (tok) headers[\"Authorization\"] = `Bearer ${tok}`;\r\n }\r\n\r\n const res = await fetch(url, {\r\n ...opts,\r\n headers: { ...headers, ...(opts.headers || {}) },\r\n });\r\n\r\n if (!res.ok) {\r\n let message = `Request failed (${res.status})`;\r\n const contentType = res.headers.get(\"content-type\") || \"\";\r\n\r\n // Backend returned JSON error\r\n if (contentType.includes(\"application/json\")) {\r\n try {\r\n const data = await res.json();\r\n if (data?.message) message = data.message;\r\n } catch {\r\n // ignore JSON parse errors, can come back later\r\n }\r\n }\r\n\r\n // Backend returned HTML (Express default error pages)\r\n if (contentType.includes(\"text/html\")) {\r\n if (res.status === 404 && url.includes(\"forgot\")) {\r\n message =\r\n \"The forgot password endpoint you added in config.endpoints.forgot does not exist in your server. Please check and update your config.endpoints.forgot\";\r\n } else {\r\n message = \"Unexpected server error\";\r\n }\r\n }\r\n\r\n // Developer-only guidance\r\n if (res.status === 404 && url.includes(\"forgot\")) {\r\n console.error(\r\n `[auth-flow-kit] Password reset endpoint not found.\r\n\r\n Expected a POST route matching:\r\n ${url}\r\n\r\n Fix this by either:\r\n - Adding the route on your backend, or\r\n - Updating config.endpoints.forgot`,\r\n );\r\n }\r\n\r\n throw new Error(message);\r\n }\r\n\r\n return res.json() as Promise<T>;\r\n}\r\n","\"use client\";\r\n\r\n/*\r\nProtected component\r\n\r\nWraps authenticated content and prevents rendering when unauthenticated.\r\n\r\nIMPORTANT:\r\nThis component does NOT hard-redirect by default.\r\nNavigation should be handled by the host application (router or state).\r\n\r\nIf redirectTo is provided AND the host app supports routing,\r\na redirect will occur.\r\n*/\r\n\r\nimport React, { useEffect } from \"react\";\r\nimport { useAuth } from \"./AuthContext\";\r\n\r\ntype ProtectedProps = {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n};\r\n\r\nexport default function Protected({ children, redirectTo }: ProtectedProps) {\r\n const { user, loading } = useAuth();\r\n\r\n useEffect(() => {\r\n if (!loading && !user && redirectTo) {\r\n window.location.href = redirectTo;\r\n }\r\n }, [loading, user, redirectTo]);\r\n\r\n if (loading) return <div>Loading...</div>;\r\n if (!user) return null;\r\n\r\n return <>{children}</>;\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport PasswordResetScreen from \"./PasswordResetScreen\";\r\n\r\nexport default function LoginScreen() {\r\n const { login } = useAuth();\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [showReset, setShowReset] = useState(false);\r\n\r\n if (showReset) {\r\n return (\r\n <div style={{ animation: \"fade .2s\" }}>\r\n <PasswordResetScreen />\r\n <p\r\n onClick={() => setShowReset(false)}\r\n style={{\r\n marginTop: 16,\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n textDecoration: \"underline\",\r\n }}\r\n >\r\n Back to login\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Submit\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await login(trimmedEmail, trimmedPassword);\r\n } catch (err: any) {\r\n setError(err?.message || \"Login failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Welcome Back 👋\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 10 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <p\r\n onClick={() => setShowReset(true)}\r\n style={{\r\n textAlign: \"right\",\r\n fontSize: 13,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n marginBottom: 24,\r\n }}\r\n >\r\n Forgot password?\r\n </p>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Signing in...\" : \"Sign in\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport { httpJSON, makeURL } from \"../http\";\r\n\r\nexport default function PasswordResetScreen() {\r\n const { config } = useAuth();\r\n\r\n const [email, setEmail] = useState(\"\");\r\n const [sent, setSent] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const requestReset = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n try {\r\n const url = makeURL(config.baseURL, config.endpoints.forgot);\r\n\r\n await httpJSON(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email }),\r\n });\r\n\r\n setSent(true);\r\n } catch (err: any) {\r\n setError(err?.message || \"Failed to request reset\");\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={requestReset}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.25s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Reset Password 🔑\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: sent ? \"-18px\" : \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"90%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: sent\r\n ? \"linear-gradient(90deg, #7aff9d, #34c759)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.3s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {sent ? \"Link Sent ✔\" : \"Send reset link\"}\r\n </button>\r\n\r\n {sent && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"#2ecc71\",\r\n textAlign: \"center\",\r\n fontSize: 15,\r\n fontWeight: 600,\r\n }}\r\n >\r\n Check your email for reset instructions.\r\n </p>\r\n )}\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\n\r\nexport default function SignupScreen() {\r\n const { signup } = useAuth();\r\n const [name, setName] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n const trimmedName = name.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword || !trimmedName) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await signup({ name, email, password });\r\n } catch (err: any) {\r\n setError(err?.message || \"Signup failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Create Account ✨\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Name\r\n </label>\r\n\r\n <input\r\n value={name}\r\n onChange={(e) => setName(e.target.value)}\r\n placeholder=\"Your name\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Creating...\" : \"Create account\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AuthContext.tsx","../src/http.ts","../src/Protected.tsx","../src/screens/LoginScreen.tsx","../src/screens/PasswordResetScreen.tsx","../src/screens/SignupScreen.tsx"],"sourcesContent":["export { AuthProvider, useAuth } from \"./AuthContext\";\r\nexport { default as Protected } from \"./Protected\";\r\n\r\n// Screens\r\nexport { default as LoginScreen } from \"./screens/LoginScreen\";\r\nexport { default as SignupScreen } from \"./screens/SignupScreen\";\r\nexport { default as PasswordResetScreen } from \"./screens/PasswordResetScreen\";\r\n\r\n// Types\r\nexport * from \"./types\";\r\n","/* \r\nDevelopers using this library should wrap their app with:\r\n <AuthProvider config={...}>\r\n <App />\r\n </AuthProvider>\r\n \r\n Then they can access auth anywhere with:\r\n const { user, login, logout, getToken } = useAuth();\r\n*/\r\n\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useState,\r\n} from \"react\";\r\n\r\nimport {\r\n AuthContextType,\r\n AuthProviderConfig,\r\n StandardAuthResponse,\r\n User,\r\n} from \"./types\";\r\n\r\nimport {\r\n httpJSON,\r\n makeURL,\r\n setStoredAccessToken,\r\n getStoredAccessToken,\r\n} from \"./http\";\r\n\r\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\r\n\r\nexport function useAuth(): AuthContextType {\r\n const ctx = useContext(AuthContext);\r\n if (!ctx) throw new Error(\"useAuth must be used inside AuthProvider\");\r\n return ctx;\r\n}\r\n\r\nexport function AuthProvider({\r\n config,\r\n children,\r\n}: React.PropsWithChildren<{ config: AuthProviderConfig }>) {\r\n const { baseURL, endpoints, onLoginSuccess, onLogout } = config;\r\n\r\n const [user, setUser] = useState<User | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n const getToken = () => getStoredAccessToken();\r\n\r\n // Restore user from localStorage on app load\r\n useEffect(() => {\r\n const savedUser = localStorage.getItem(\"afk_user\");\r\n if (savedUser) {\r\n setUser(JSON.parse(savedUser));\r\n }\r\n setLoading(false);\r\n }, []);\r\n\r\n // LOGIN\r\n const login: AuthContextType[\"login\"] = async (email, password) => {\r\n const url = makeURL(baseURL, endpoints.login);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email, password }),\r\n });\r\n\r\n // store token + user\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // SIGNUP\r\n const signup: AuthContextType[\"signup\"] = async (payload) => {\r\n const url = makeURL(baseURL, endpoints.signup);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify(payload),\r\n });\r\n\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // LOGOUT\r\n const logout = () => {\r\n setStoredAccessToken(null);\r\n localStorage.removeItem(\"afk_user\");\r\n setUser(null);\r\n\r\n if (onLogout) onLogout();\r\n };\r\n\r\n const value = useMemo<AuthContextType>(\r\n () => ({\r\n user,\r\n loading,\r\n login,\r\n signup,\r\n logout,\r\n getToken,\r\n config,\r\n }),\r\n [user, loading, config],\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n","/*\r\n Internal HTTP helpers for auth-flow-kit.\r\n\r\n Responsibilities:\r\n • Construct safe URLs (makeURL)\r\n • Persist access token (get/set)\r\n • Perform JSON requests with optional auth (httpJSON)\r\n\r\n ⚠️ Library users should NOT import this directly.\r\n Used internally by AuthProvider + auth UI.\r\n\r\n Design goals:\r\n - predictable\r\n - minimal\r\n - RTK-style familiarity\r\n*/\r\n\r\nexport function makeURL(baseURL: string, path: string) {\r\n const cleanedBase = baseURL.replace(/\\/$/, \"\");\r\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\r\n return `${cleanedBase}${normalizedPath}`;\r\n}\r\n\r\nexport function getStoredAccessToken(): string | null {\r\n try {\r\n const token = localStorage.getItem(\"afk_access_token\");\r\n return token;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function setStoredAccessToken(token: string | null) {\r\n try {\r\n if (!token) {\r\n localStorage.removeItem(\"afk_access_token\");\r\n return;\r\n }\r\n\r\n localStorage.setItem(\"afk_access_token\", token);\r\n } catch {\r\n // Swallow storage issues (e.g. private mode)\r\n }\r\n}\r\n\r\nexport async function httpJSON<T>(\r\n url: string,\r\n opts: RequestInit = {},\r\n withAuth = false,\r\n): Promise<T> {\r\n const baseHeaders: Record<string, string> = {\r\n \"Content-Type\": \"application/json\",\r\n };\r\n\r\n if (withAuth) {\r\n const token = getStoredAccessToken();\r\n if (token) {\r\n baseHeaders[\"Authorization\"] = `Bearer ${token}`;\r\n }\r\n }\r\n\r\n const response = await fetch(url, {\r\n ...opts,\r\n headers: {\r\n ...baseHeaders,\r\n ...(opts.headers ?? {}),\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n const contentType = response.headers.get(\"content-type\") ?? \"\";\r\n let errorMessage = `Request failed (${response.status})`;\r\n\r\n // JSON error handling\r\n if (contentType.includes(\"application/json\")) {\r\n try {\r\n const payload = await response.json();\r\n if (payload?.message) {\r\n errorMessage = payload.message;\r\n }\r\n } catch {\r\n // ignore malformed JSON\r\n }\r\n }\r\n\r\n // HTML fallback (common in Express)\r\n if (contentType.includes(\"text/html\")) {\r\n if (response.status === 404 && url.includes(\"forgot\")) {\r\n errorMessage =\r\n \"The forgot password endpoint you added in config.endpoints.forgot does not exist in your server. Please check and update your config.endpoints.forgot\";\r\n } else {\r\n errorMessage = \"Unexpected server error\";\r\n }\r\n }\r\n\r\n // Dev hint for common misconfig\r\n if (response.status === 404 && url.includes(\"forgot\")) {\r\n console.error(\r\n `[auth-flow-kit] Password reset endpoint not found.\r\n\r\nExpected POST route:\r\n ${url}\r\n\r\nFix by:\r\n • Adding the endpoint on your backend\r\n • OR updating config.endpoints.forgot`,\r\n );\r\n }\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n}\r\n","\"use client\";\r\n\r\n/*\r\nProtected component\r\n\r\nWraps authenticated content and prevents rendering when unauthenticated.\r\n\r\nIMPORTANT:\r\nThis component does NOT hard-redirect by default.\r\nNavigation should be handled by the host application (router or state).\r\n\r\nIf redirectTo is provided AND the host app supports routing,\r\na redirect will occur.\r\n*/\r\n\r\nimport React, { useEffect } from \"react\";\r\nimport { useAuth } from \"./AuthContext\";\r\n\r\ntype ProtectedProps = {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n};\r\n\r\nexport default function Protected({ children, redirectTo }: ProtectedProps) {\r\n const { user, loading } = useAuth();\r\n\r\n useEffect(() => {\r\n if (!loading && !user && redirectTo) {\r\n window.location.href = redirectTo;\r\n }\r\n }, [loading, user, redirectTo]);\r\n\r\n if (loading) return <div>Loading...</div>;\r\n if (!user) return null;\r\n\r\n return <>{children}</>;\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport PasswordResetScreen from \"./PasswordResetScreen\";\r\n\r\nexport default function LoginScreen() {\r\n const { login } = useAuth();\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [showReset, setShowReset] = useState(false);\r\n\r\n if (showReset) {\r\n return (\r\n <div style={{ animation: \"fade .2s\" }}>\r\n <PasswordResetScreen />\r\n <p\r\n onClick={() => setShowReset(false)}\r\n style={{\r\n marginTop: 16,\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n textDecoration: \"underline\",\r\n }}\r\n >\r\n Back to login\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Submit\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await login(trimmedEmail, trimmedPassword);\r\n } catch (err: any) {\r\n setError(err?.message || \"Login failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Welcome Back 👋\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 10 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <p\r\n onClick={() => setShowReset(true)}\r\n style={{\r\n textAlign: \"right\",\r\n fontSize: 13,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n marginBottom: 24,\r\n }}\r\n >\r\n Forgot password?\r\n </p>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Signing in...\" : \"Sign in\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport { httpJSON, makeURL } from \"../http\";\r\n\r\nexport default function PasswordResetScreen() {\r\n const { config } = useAuth();\r\n\r\n const [email, setEmail] = useState(\"\");\r\n const [sent, setSent] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const requestReset = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n try {\r\n const url = makeURL(config.baseURL, config.endpoints.forgot);\r\n\r\n await httpJSON(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email }),\r\n });\r\n\r\n setSent(true);\r\n } catch (err: any) {\r\n setError(err?.message || \"Failed to request reset\");\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={requestReset}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.25s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Reset Password 🔑\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: sent ? \"-18px\" : \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"90%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: sent\r\n ? \"linear-gradient(90deg, #7aff9d, #34c759)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.3s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {sent ? \"Link Sent ✔\" : \"Send reset link\"}\r\n </button>\r\n\r\n {sent && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"#2ecc71\",\r\n textAlign: \"center\",\r\n fontSize: 15,\r\n fontWeight: 600,\r\n }}\r\n >\r\n Check your email for reset instructions.\r\n </p>\r\n )}\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\n\r\nexport default function SignupScreen() {\r\n const { signup } = useAuth();\r\n const [name, setName] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n const trimmedName = name.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword || !trimmedName) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await signup({ name, email, password });\r\n } catch (err: any) {\r\n setError(err?.message || \"Signup failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Create Account ✨\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Name\r\n </label>\r\n\r\n <input\r\n value={name}\r\n onChange={(e) => setName(e.target.value)}\r\n placeholder=\"Your name\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Creating...\" : \"Create account\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime"]}
|
package/dist/index.js
CHANGED
|
@@ -9,66 +9,79 @@ import {
|
|
|
9
9
|
|
|
10
10
|
// src/http.ts
|
|
11
11
|
function makeURL(baseURL, path) {
|
|
12
|
-
|
|
12
|
+
const cleanedBase = baseURL.replace(/\/$/, "");
|
|
13
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
14
|
+
return `${cleanedBase}${normalizedPath}`;
|
|
13
15
|
}
|
|
14
16
|
function getStoredAccessToken() {
|
|
15
17
|
try {
|
|
16
|
-
|
|
18
|
+
const token = localStorage.getItem("afk_access_token");
|
|
19
|
+
return token;
|
|
17
20
|
} catch {
|
|
18
21
|
return null;
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
24
|
function setStoredAccessToken(token) {
|
|
22
25
|
try {
|
|
23
|
-
if (token)
|
|
24
|
-
|
|
26
|
+
if (!token) {
|
|
27
|
+
localStorage.removeItem("afk_access_token");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
localStorage.setItem("afk_access_token", token);
|
|
25
31
|
} catch {
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
async function httpJSON(url, opts = {}, withAuth = false) {
|
|
29
|
-
const
|
|
35
|
+
const baseHeaders = {
|
|
30
36
|
"Content-Type": "application/json"
|
|
31
37
|
};
|
|
32
38
|
if (withAuth) {
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
39
|
+
const token = getStoredAccessToken();
|
|
40
|
+
if (token) {
|
|
41
|
+
baseHeaders["Authorization"] = `Bearer ${token}`;
|
|
42
|
+
}
|
|
35
43
|
}
|
|
36
|
-
const
|
|
44
|
+
const response = await fetch(url, {
|
|
37
45
|
...opts,
|
|
38
|
-
headers: {
|
|
46
|
+
headers: {
|
|
47
|
+
...baseHeaders,
|
|
48
|
+
...opts.headers ?? {}
|
|
49
|
+
}
|
|
39
50
|
});
|
|
40
|
-
if (!
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
53
|
+
let errorMessage = `Request failed (${response.status})`;
|
|
43
54
|
if (contentType.includes("application/json")) {
|
|
44
55
|
try {
|
|
45
|
-
const
|
|
46
|
-
if (
|
|
56
|
+
const payload = await response.json();
|
|
57
|
+
if (payload?.message) {
|
|
58
|
+
errorMessage = payload.message;
|
|
59
|
+
}
|
|
47
60
|
} catch {
|
|
48
61
|
}
|
|
49
62
|
}
|
|
50
63
|
if (contentType.includes("text/html")) {
|
|
51
|
-
if (
|
|
52
|
-
|
|
64
|
+
if (response.status === 404 && url.includes("forgot")) {
|
|
65
|
+
errorMessage = "The forgot password endpoint you added in config.endpoints.forgot does not exist in your server. Please check and update your config.endpoints.forgot";
|
|
53
66
|
} else {
|
|
54
|
-
|
|
67
|
+
errorMessage = "Unexpected server error";
|
|
55
68
|
}
|
|
56
69
|
}
|
|
57
|
-
if (
|
|
70
|
+
if (response.status === 404 && url.includes("forgot")) {
|
|
58
71
|
console.error(
|
|
59
72
|
`[auth-flow-kit] Password reset endpoint not found.
|
|
60
73
|
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
Expected POST route:
|
|
75
|
+
${url}
|
|
63
76
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
Fix by:
|
|
78
|
+
\u2022 Adding the endpoint on your backend
|
|
79
|
+
\u2022 OR updating config.endpoints.forgot`
|
|
67
80
|
);
|
|
68
81
|
}
|
|
69
|
-
throw new Error(
|
|
82
|
+
throw new Error(errorMessage);
|
|
70
83
|
}
|
|
71
|
-
return
|
|
84
|
+
return response.json();
|
|
72
85
|
}
|
|
73
86
|
|
|
74
87
|
// src/AuthContext.tsx
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AuthContext.tsx","../src/http.ts","../src/Protected.tsx","../src/screens/LoginScreen.tsx","../src/screens/PasswordResetScreen.tsx","../src/screens/SignupScreen.tsx"],"sourcesContent":["/* \r\nDevelopers using this library should wrap their app with:\r\n <AuthProvider config={...}>\r\n <App />\r\n </AuthProvider>\r\n \r\n Then they can access auth anywhere with:\r\n const { user, login, logout, getToken } = useAuth();\r\n*/\r\n\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useState,\r\n} from \"react\";\r\n\r\nimport {\r\n AuthContextType,\r\n AuthProviderConfig,\r\n StandardAuthResponse,\r\n User,\r\n} from \"./types\";\r\n\r\nimport {\r\n httpJSON,\r\n makeURL,\r\n setStoredAccessToken,\r\n getStoredAccessToken,\r\n} from \"./http\";\r\n\r\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\r\n\r\nexport function useAuth(): AuthContextType {\r\n const ctx = useContext(AuthContext);\r\n if (!ctx) throw new Error(\"useAuth must be used inside AuthProvider\");\r\n return ctx;\r\n}\r\n\r\nexport function AuthProvider({\r\n config,\r\n children,\r\n}: React.PropsWithChildren<{ config: AuthProviderConfig }>) {\r\n const { baseURL, endpoints, onLoginSuccess, onLogout } = config;\r\n\r\n const [user, setUser] = useState<User | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n const getToken = () => getStoredAccessToken();\r\n\r\n // Restore user from localStorage on app load\r\n useEffect(() => {\r\n const savedUser = localStorage.getItem(\"afk_user\");\r\n if (savedUser) {\r\n setUser(JSON.parse(savedUser));\r\n }\r\n setLoading(false);\r\n }, []);\r\n\r\n // LOGIN\r\n const login: AuthContextType[\"login\"] = async (email, password) => {\r\n const url = makeURL(baseURL, endpoints.login);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email, password }),\r\n });\r\n\r\n // store token + user\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // SIGNUP\r\n const signup: AuthContextType[\"signup\"] = async (payload) => {\r\n const url = makeURL(baseURL, endpoints.signup);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify(payload),\r\n });\r\n\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // LOGOUT\r\n const logout = () => {\r\n setStoredAccessToken(null);\r\n localStorage.removeItem(\"afk_user\");\r\n setUser(null);\r\n\r\n if (onLogout) onLogout();\r\n };\r\n\r\n const value = useMemo<AuthContextType>(\r\n () => ({\r\n user,\r\n loading,\r\n login,\r\n signup,\r\n logout,\r\n getToken,\r\n config,\r\n }),\r\n [user, loading, config],\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n","/*\r\n This file contains the low-level HTTP utilities used internally by\r\n auth-flow-kit to communicate with the backend.\r\n\r\n It provides:\r\n - makeURL: safely joins baseURL + endpoint path\r\n - getStoredAccessToken: reads the JWT from localStorage\r\n - setStoredAccessToken: stores/removes the JWT\r\n - httpJSON: wrapper around fetch with JSON + optional auth header\r\n\r\n NOTES FOR DEVELOPERS USING THE LIBRARY:\r\n You do NOT need to import or modify anything in this file.\r\n It is an internal helper used by the AuthProvider and auth screens.\r\n\r\n This keeps the library lightweight, predictable,\r\n and familiar to developers used to Redux Toolkit-style authentication.\r\n*/\r\n\r\nexport function makeURL(baseURL: string, path: string) {\r\n return `${baseURL.replace(/\\/$/, \"\")}${\r\n path.startsWith(\"/\") ? path : `/${path}`\r\n }`;\r\n}\r\n\r\nexport function getStoredAccessToken(): string | null {\r\n try {\r\n return localStorage.getItem(\"afk_access_token\");\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function setStoredAccessToken(token: string | null) {\r\n try {\r\n if (token) localStorage.setItem(\"afk_access_token\", token);\r\n else localStorage.removeItem(\"afk_access_token\");\r\n } catch {\r\n // ignore storage errors (Safari private mode, etc.) for now, not exactly needed.\r\n }\r\n}\r\n\r\nexport async function httpJSON<T>(\r\n url: string,\r\n opts: RequestInit = {},\r\n withAuth = false,\r\n): Promise<T> {\r\n const headers: Record<string, string> = {\r\n \"Content-Type\": \"application/json\",\r\n };\r\n\r\n if (withAuth) {\r\n const tok = getStoredAccessToken();\r\n if (tok) headers[\"Authorization\"] = `Bearer ${tok}`;\r\n }\r\n\r\n const res = await fetch(url, {\r\n ...opts,\r\n headers: { ...headers, ...(opts.headers || {}) },\r\n });\r\n\r\n if (!res.ok) {\r\n let message = `Request failed (${res.status})`;\r\n const contentType = res.headers.get(\"content-type\") || \"\";\r\n\r\n // Backend returned JSON error\r\n if (contentType.includes(\"application/json\")) {\r\n try {\r\n const data = await res.json();\r\n if (data?.message) message = data.message;\r\n } catch {\r\n // ignore JSON parse errors, can come back later\r\n }\r\n }\r\n\r\n // Backend returned HTML (Express default error pages)\r\n if (contentType.includes(\"text/html\")) {\r\n if (res.status === 404 && url.includes(\"forgot\")) {\r\n message =\r\n \"The forgot password endpoint you added in config.endpoints.forgot does not exist in your server. Please check and update your config.endpoints.forgot\";\r\n } else {\r\n message = \"Unexpected server error\";\r\n }\r\n }\r\n\r\n // Developer-only guidance\r\n if (res.status === 404 && url.includes(\"forgot\")) {\r\n console.error(\r\n `[auth-flow-kit] Password reset endpoint not found.\r\n\r\n Expected a POST route matching:\r\n ${url}\r\n\r\n Fix this by either:\r\n - Adding the route on your backend, or\r\n - Updating config.endpoints.forgot`,\r\n );\r\n }\r\n\r\n throw new Error(message);\r\n }\r\n\r\n return res.json() as Promise<T>;\r\n}\r\n","\"use client\";\r\n\r\n/*\r\nProtected component\r\n\r\nWraps authenticated content and prevents rendering when unauthenticated.\r\n\r\nIMPORTANT:\r\nThis component does NOT hard-redirect by default.\r\nNavigation should be handled by the host application (router or state).\r\n\r\nIf redirectTo is provided AND the host app supports routing,\r\na redirect will occur.\r\n*/\r\n\r\nimport React, { useEffect } from \"react\";\r\nimport { useAuth } from \"./AuthContext\";\r\n\r\ntype ProtectedProps = {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n};\r\n\r\nexport default function Protected({ children, redirectTo }: ProtectedProps) {\r\n const { user, loading } = useAuth();\r\n\r\n useEffect(() => {\r\n if (!loading && !user && redirectTo) {\r\n window.location.href = redirectTo;\r\n }\r\n }, [loading, user, redirectTo]);\r\n\r\n if (loading) return <div>Loading...</div>;\r\n if (!user) return null;\r\n\r\n return <>{children}</>;\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport PasswordResetScreen from \"./PasswordResetScreen\";\r\n\r\nexport default function LoginScreen() {\r\n const { login } = useAuth();\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [showReset, setShowReset] = useState(false);\r\n\r\n if (showReset) {\r\n return (\r\n <div style={{ animation: \"fade .2s\" }}>\r\n <PasswordResetScreen />\r\n <p\r\n onClick={() => setShowReset(false)}\r\n style={{\r\n marginTop: 16,\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n textDecoration: \"underline\",\r\n }}\r\n >\r\n Back to login\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Submit\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await login(trimmedEmail, trimmedPassword);\r\n } catch (err: any) {\r\n setError(err?.message || \"Login failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Welcome Back 👋\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 10 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <p\r\n onClick={() => setShowReset(true)}\r\n style={{\r\n textAlign: \"right\",\r\n fontSize: 13,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n marginBottom: 24,\r\n }}\r\n >\r\n Forgot password?\r\n </p>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Signing in...\" : \"Sign in\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport { httpJSON, makeURL } from \"../http\";\r\n\r\nexport default function PasswordResetScreen() {\r\n const { config } = useAuth();\r\n\r\n const [email, setEmail] = useState(\"\");\r\n const [sent, setSent] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const requestReset = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n try {\r\n const url = makeURL(config.baseURL, config.endpoints.forgot);\r\n\r\n await httpJSON(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email }),\r\n });\r\n\r\n setSent(true);\r\n } catch (err: any) {\r\n setError(err?.message || \"Failed to request reset\");\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={requestReset}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.25s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Reset Password 🔑\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: sent ? \"-18px\" : \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"90%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: sent\r\n ? \"linear-gradient(90deg, #7aff9d, #34c759)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.3s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {sent ? \"Link Sent ✔\" : \"Send reset link\"}\r\n </button>\r\n\r\n {sent && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"#2ecc71\",\r\n textAlign: \"center\",\r\n fontSize: 15,\r\n fontWeight: 600,\r\n }}\r\n >\r\n Check your email for reset instructions.\r\n </p>\r\n )}\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\n\r\nexport default function SignupScreen() {\r\n const { signup } = useAuth();\r\n const [name, setName] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n const trimmedName = name.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword || !trimmedName) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await signup({ name, email, password });\r\n } catch (err: any) {\r\n setError(err?.message || \"Signup failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Create Account ✨\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Name\r\n </label>\r\n\r\n <input\r\n value={name}\r\n onChange={(e) => setName(e.target.value)}\r\n placeholder=\"Your name\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Creating...\" : \"Create account\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n"],"mappings":"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","names":["useEffect","jsx","useEffect","useState","useState","jsx","useState","jsx","jsxs","useState","useState","jsx","jsxs","useState"]}
|
|
1
|
+
{"version":3,"sources":["../src/AuthContext.tsx","../src/http.ts","../src/Protected.tsx","../src/screens/LoginScreen.tsx","../src/screens/PasswordResetScreen.tsx","../src/screens/SignupScreen.tsx"],"sourcesContent":["/* \r\nDevelopers using this library should wrap their app with:\r\n <AuthProvider config={...}>\r\n <App />\r\n </AuthProvider>\r\n \r\n Then they can access auth anywhere with:\r\n const { user, login, logout, getToken } = useAuth();\r\n*/\r\n\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useState,\r\n} from \"react\";\r\n\r\nimport {\r\n AuthContextType,\r\n AuthProviderConfig,\r\n StandardAuthResponse,\r\n User,\r\n} from \"./types\";\r\n\r\nimport {\r\n httpJSON,\r\n makeURL,\r\n setStoredAccessToken,\r\n getStoredAccessToken,\r\n} from \"./http\";\r\n\r\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\r\n\r\nexport function useAuth(): AuthContextType {\r\n const ctx = useContext(AuthContext);\r\n if (!ctx) throw new Error(\"useAuth must be used inside AuthProvider\");\r\n return ctx;\r\n}\r\n\r\nexport function AuthProvider({\r\n config,\r\n children,\r\n}: React.PropsWithChildren<{ config: AuthProviderConfig }>) {\r\n const { baseURL, endpoints, onLoginSuccess, onLogout } = config;\r\n\r\n const [user, setUser] = useState<User | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n const getToken = () => getStoredAccessToken();\r\n\r\n // Restore user from localStorage on app load\r\n useEffect(() => {\r\n const savedUser = localStorage.getItem(\"afk_user\");\r\n if (savedUser) {\r\n setUser(JSON.parse(savedUser));\r\n }\r\n setLoading(false);\r\n }, []);\r\n\r\n // LOGIN\r\n const login: AuthContextType[\"login\"] = async (email, password) => {\r\n const url = makeURL(baseURL, endpoints.login);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email, password }),\r\n });\r\n\r\n // store token + user\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // SIGNUP\r\n const signup: AuthContextType[\"signup\"] = async (payload) => {\r\n const url = makeURL(baseURL, endpoints.signup);\r\n\r\n const res = await httpJSON<StandardAuthResponse>(url, {\r\n method: \"POST\",\r\n body: JSON.stringify(payload),\r\n });\r\n\r\n setStoredAccessToken(res.accessToken);\r\n localStorage.setItem(\"afk_user\", JSON.stringify(res.user));\r\n\r\n setUser(res.user);\r\n\r\n if (onLoginSuccess) onLoginSuccess();\r\n };\r\n\r\n // LOGOUT\r\n const logout = () => {\r\n setStoredAccessToken(null);\r\n localStorage.removeItem(\"afk_user\");\r\n setUser(null);\r\n\r\n if (onLogout) onLogout();\r\n };\r\n\r\n const value = useMemo<AuthContextType>(\r\n () => ({\r\n user,\r\n loading,\r\n login,\r\n signup,\r\n logout,\r\n getToken,\r\n config,\r\n }),\r\n [user, loading, config],\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n","/*\r\n Internal HTTP helpers for auth-flow-kit.\r\n\r\n Responsibilities:\r\n • Construct safe URLs (makeURL)\r\n • Persist access token (get/set)\r\n • Perform JSON requests with optional auth (httpJSON)\r\n\r\n ⚠️ Library users should NOT import this directly.\r\n Used internally by AuthProvider + auth UI.\r\n\r\n Design goals:\r\n - predictable\r\n - minimal\r\n - RTK-style familiarity\r\n*/\r\n\r\nexport function makeURL(baseURL: string, path: string) {\r\n const cleanedBase = baseURL.replace(/\\/$/, \"\");\r\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\r\n return `${cleanedBase}${normalizedPath}`;\r\n}\r\n\r\nexport function getStoredAccessToken(): string | null {\r\n try {\r\n const token = localStorage.getItem(\"afk_access_token\");\r\n return token;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function setStoredAccessToken(token: string | null) {\r\n try {\r\n if (!token) {\r\n localStorage.removeItem(\"afk_access_token\");\r\n return;\r\n }\r\n\r\n localStorage.setItem(\"afk_access_token\", token);\r\n } catch {\r\n // Swallow storage issues (e.g. private mode)\r\n }\r\n}\r\n\r\nexport async function httpJSON<T>(\r\n url: string,\r\n opts: RequestInit = {},\r\n withAuth = false,\r\n): Promise<T> {\r\n const baseHeaders: Record<string, string> = {\r\n \"Content-Type\": \"application/json\",\r\n };\r\n\r\n if (withAuth) {\r\n const token = getStoredAccessToken();\r\n if (token) {\r\n baseHeaders[\"Authorization\"] = `Bearer ${token}`;\r\n }\r\n }\r\n\r\n const response = await fetch(url, {\r\n ...opts,\r\n headers: {\r\n ...baseHeaders,\r\n ...(opts.headers ?? {}),\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n const contentType = response.headers.get(\"content-type\") ?? \"\";\r\n let errorMessage = `Request failed (${response.status})`;\r\n\r\n // JSON error handling\r\n if (contentType.includes(\"application/json\")) {\r\n try {\r\n const payload = await response.json();\r\n if (payload?.message) {\r\n errorMessage = payload.message;\r\n }\r\n } catch {\r\n // ignore malformed JSON\r\n }\r\n }\r\n\r\n // HTML fallback (common in Express)\r\n if (contentType.includes(\"text/html\")) {\r\n if (response.status === 404 && url.includes(\"forgot\")) {\r\n errorMessage =\r\n \"The forgot password endpoint you added in config.endpoints.forgot does not exist in your server. Please check and update your config.endpoints.forgot\";\r\n } else {\r\n errorMessage = \"Unexpected server error\";\r\n }\r\n }\r\n\r\n // Dev hint for common misconfig\r\n if (response.status === 404 && url.includes(\"forgot\")) {\r\n console.error(\r\n `[auth-flow-kit] Password reset endpoint not found.\r\n\r\nExpected POST route:\r\n ${url}\r\n\r\nFix by:\r\n • Adding the endpoint on your backend\r\n • OR updating config.endpoints.forgot`,\r\n );\r\n }\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n return response.json() as Promise<T>;\r\n}\r\n","\"use client\";\r\n\r\n/*\r\nProtected component\r\n\r\nWraps authenticated content and prevents rendering when unauthenticated.\r\n\r\nIMPORTANT:\r\nThis component does NOT hard-redirect by default.\r\nNavigation should be handled by the host application (router or state).\r\n\r\nIf redirectTo is provided AND the host app supports routing,\r\na redirect will occur.\r\n*/\r\n\r\nimport React, { useEffect } from \"react\";\r\nimport { useAuth } from \"./AuthContext\";\r\n\r\ntype ProtectedProps = {\r\n children: React.ReactNode;\r\n redirectTo?: string;\r\n};\r\n\r\nexport default function Protected({ children, redirectTo }: ProtectedProps) {\r\n const { user, loading } = useAuth();\r\n\r\n useEffect(() => {\r\n if (!loading && !user && redirectTo) {\r\n window.location.href = redirectTo;\r\n }\r\n }, [loading, user, redirectTo]);\r\n\r\n if (loading) return <div>Loading...</div>;\r\n if (!user) return null;\r\n\r\n return <>{children}</>;\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport PasswordResetScreen from \"./PasswordResetScreen\";\r\n\r\nexport default function LoginScreen() {\r\n const { login } = useAuth();\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [showReset, setShowReset] = useState(false);\r\n\r\n if (showReset) {\r\n return (\r\n <div style={{ animation: \"fade .2s\" }}>\r\n <PasswordResetScreen />\r\n <p\r\n onClick={() => setShowReset(false)}\r\n style={{\r\n marginTop: 16,\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n textDecoration: \"underline\",\r\n }}\r\n >\r\n Back to login\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Submit\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await login(trimmedEmail, trimmedPassword);\r\n } catch (err: any) {\r\n setError(err?.message || \"Login failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Welcome Back 👋\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 10 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.8)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <p\r\n onClick={() => setShowReset(true)}\r\n style={{\r\n textAlign: \"right\",\r\n fontSize: 13,\r\n color: \"#4b4bff\",\r\n cursor: \"pointer\",\r\n marginBottom: 24,\r\n }}\r\n >\r\n Forgot password?\r\n </p>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Signing in...\" : \"Sign in\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\nimport { httpJSON, makeURL } from \"../http\";\r\n\r\nexport default function PasswordResetScreen() {\r\n const { config } = useAuth();\r\n\r\n const [email, setEmail] = useState(\"\");\r\n const [sent, setSent] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const requestReset = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n try {\r\n const url = makeURL(config.baseURL, config.endpoints.forgot);\r\n\r\n await httpJSON(url, {\r\n method: \"POST\",\r\n body: JSON.stringify({ email }),\r\n });\r\n\r\n setSent(true);\r\n } catch (err: any) {\r\n setError(err?.message || \"Failed to request reset\");\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={requestReset}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.25s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Reset Password 🔑\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: sent ? \"-18px\" : \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"90%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n\r\n background: sent\r\n ? \"linear-gradient(90deg, #7aff9d, #34c759)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.3s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {sent ? \"Link Sent ✔\" : \"Send reset link\"}\r\n </button>\r\n\r\n {sent && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"#2ecc71\",\r\n textAlign: \"center\",\r\n fontSize: 15,\r\n fontWeight: 600,\r\n }}\r\n >\r\n Check your email for reset instructions.\r\n </p>\r\n )}\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 20,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n","\"use client\";\r\nimport React, { useState } from \"react\";\r\nimport { useAuth } from \"../AuthContext\";\r\n\r\nexport default function SignupScreen() {\r\n const { signup } = useAuth();\r\n const [name, setName] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [submitting, setSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const onSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSubmitting(true);\r\n setError(null);\r\n\r\n const trimmedEmail = email.trim();\r\n const trimmedPassword = password.trim();\r\n const trimmedName = name.trim();\r\n\r\n if (!trimmedEmail || !trimmedPassword || !trimmedName) {\r\n setError(\"Email and password cannot be empty.\");\r\n setSubmitting(false);\r\n return;\r\n }\r\n\r\n try {\r\n await signup({ name, email, password });\r\n } catch (err: any) {\r\n setError(err?.message || \"Signup failed\");\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n return (\r\n <form\r\n onSubmit={onSubmit}\r\n style={{\r\n maxWidth: 400,\r\n margin: \"60px auto\",\r\n padding: 32,\r\n borderRadius: 20,\r\n fontFamily: \"Inter, sans-serif\",\r\n\r\n // GLASS EFFECT\r\n background: \"rgba(255, 255, 255, 0.25)\",\r\n backdropFilter: \"blur(14px)\",\r\n WebkitBackdropFilter: \"blur(14px)\",\r\n\r\n boxShadow: \"0 20px 40px rgba(0,0,0,0.15)\",\r\n border: \"1px solid rgba(255,255,255,0.4)\",\r\n animation: \"fadeIn 0.3s ease\",\r\n }}\r\n >\r\n <h2\r\n style={{\r\n marginBottom: 30,\r\n color: \"#060f22\",\r\n fontWeight: 700,\r\n fontSize: 30,\r\n textAlign: \"center\",\r\n letterSpacing: \"-0.5px\",\r\n }}\r\n >\r\n Create Account ✨\r\n </h2>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Name\r\n </label>\r\n\r\n <input\r\n value={name}\r\n onChange={(e) => setName(e.target.value)}\r\n placeholder=\"Your name\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Email\r\n </label>\r\n\r\n <input\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n type=\"email\"\r\n placeholder=\"you@example.com\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <div style={{ position: \"relative\", marginBottom: 26 }}>\r\n <label\r\n style={{\r\n position: \"absolute\",\r\n top: \"-10px\",\r\n left: \"14px\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n padding: \"0 6px\",\r\n fontSize: 13,\r\n color: \"#444\",\r\n borderRadius: 6,\r\n }}\r\n >\r\n Password\r\n </label>\r\n\r\n <input\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n type=\"password\"\r\n placeholder=\"••••••••\"\r\n style={{\r\n width: \"80%\",\r\n padding: \"14px 16px\",\r\n borderRadius: 12,\r\n border: \"1px solid #d2d2d2\",\r\n fontSize: 15,\r\n outline: \"none\",\r\n transition: \"0.25s\",\r\n background: \"rgba(255,255,255,0.85)\",\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.border = \"1px solid #4b4bff\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 3px rgba(75,75,255,0.25)\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.border = \"1px solid #d2d2d2\";\r\n e.currentTarget.style.boxShadow = \"0 0 0 transparent\";\r\n }}\r\n />\r\n </div>\r\n\r\n <button\r\n disabled={submitting}\r\n type=\"submit\"\r\n style={{\r\n width: \"100%\",\r\n padding: \"14px 20px\",\r\n borderRadius: 12,\r\n background: submitting\r\n ? \"linear-gradient(90deg, #b2bdfd, #8da0ff)\"\r\n : \"linear-gradient(90deg, #5353aaff, #060f22ff)\",\r\n\r\n color: \"white\",\r\n border: \"none\",\r\n fontSize: 16,\r\n fontWeight: 700,\r\n letterSpacing: \"0.3px\",\r\n cursor: \"pointer\",\r\n transition: \"0.25s\",\r\n boxShadow: \"0 8px 20px rgba(75,75,255,0.25)\",\r\n }}\r\n >\r\n {submitting ? \"Creating...\" : \"Create account\"}\r\n </button>\r\n\r\n {error && (\r\n <p\r\n style={{\r\n marginTop: 18,\r\n color: \"crimson\",\r\n textAlign: \"center\",\r\n fontSize: 14,\r\n fontWeight: 500,\r\n }}\r\n >\r\n {error}\r\n </p>\r\n )}\r\n </form>\r\n );\r\n}\r\n"],"mappings":"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","names":["useEffect","jsx","useEffect","useState","useState","jsx","useState","jsx","jsxs","useState","useState","jsx","jsxs","useState"]}
|