@kendevelops/auth-flow-kit 1.5.0 → 1.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -34,9 +34,7 @@ var import_react = require("react");
34
34
 
35
35
  // src/http.ts
36
36
  function makeURL(baseURL, path) {
37
- const base = baseURL.replace(/\/$/, "");
38
- const suffix = path.startsWith("/") ? path : `/${path}`;
39
- return `${base}${suffix}`;
37
+ return `${baseURL.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
40
38
  }
41
39
  function getStoredAccessToken() {
42
40
  try {
@@ -47,11 +45,8 @@ function getStoredAccessToken() {
47
45
  }
48
46
  function setStoredAccessToken(token) {
49
47
  try {
50
- if (token) {
51
- localStorage.setItem("afk_access_token", token);
52
- return;
53
- }
54
- localStorage.removeItem("afk_access_token");
48
+ if (token) localStorage.setItem("afk_access_token", token);
49
+ else localStorage.removeItem("afk_access_token");
55
50
  } catch {
56
51
  }
57
52
  }
@@ -60,27 +55,20 @@ async function httpJSON(url, opts = {}, withAuth = false) {
60
55
  "Content-Type": "application/json"
61
56
  };
62
57
  if (withAuth) {
63
- const storedToken = getStoredAccessToken();
64
- if (storedToken) {
65
- headers["Authorization"] = `Bearer ${storedToken}`;
66
- }
58
+ const tok = getStoredAccessToken();
59
+ if (tok) headers["Authorization"] = `Bearer ${tok}`;
67
60
  }
68
61
  const res = await fetch(url, {
69
62
  ...opts,
70
- headers: {
71
- ...headers,
72
- ...opts.headers || {}
73
- }
63
+ headers: { ...headers, ...opts.headers || {} }
74
64
  });
75
65
  if (!res.ok) {
76
66
  let message = `Request failed (${res.status})`;
77
67
  const contentType = res.headers.get("content-type") || "";
78
68
  if (contentType.includes("application/json")) {
79
69
  try {
80
- const body = await res.json();
81
- if (body?.message) {
82
- message = body.message;
83
- }
70
+ const data = await res.json();
71
+ if (data?.message) message = data.message;
84
72
  } catch {
85
73
  }
86
74
  }
@@ -175,59 +163,43 @@ function AuthProvider({
175
163
  }
176
164
 
177
165
  // src/Protected.tsx
166
+ var import_react2 = require("react");
178
167
  var import_jsx_runtime2 = require("react/jsx-runtime");
179
- function Protected({
180
- children,
181
- redirectTo,
182
- fallback = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: "Loading..." })
183
- }) {
168
+ function Protected({ children, redirectTo }) {
184
169
  const { user, loading } = useAuth();
185
- if (loading) {
186
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
187
- }
188
- if (!user) {
189
- if (redirectTo && typeof window !== "undefined") {
190
- window.location.replace(redirectTo);
170
+ (0, import_react2.useEffect)(() => {
171
+ if (!loading && !user && redirectTo) {
172
+ window.location.href = redirectTo;
191
173
  }
192
- return null;
193
- }
174
+ }, [loading, user, redirectTo]);
175
+ if (loading) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: "Loading..." });
176
+ if (!user) return null;
194
177
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
195
178
  }
196
179
 
197
180
  // src/screens/LoginScreen.tsx
198
- var import_react3 = require("react");
181
+ var import_react4 = require("react");
199
182
 
200
183
  // src/screens/PasswordResetScreen.tsx
201
- var import_react2 = require("react");
184
+ var import_react3 = require("react");
202
185
  var import_jsx_runtime3 = require("react/jsx-runtime");
203
186
  function PasswordResetScreen() {
204
187
  const { config } = useAuth();
205
- const [email, setEmail] = (0, import_react2.useState)("");
206
- const [sent, setSent] = (0, import_react2.useState)(false);
207
- const [error, setError] = (0, import_react2.useState)(null);
208
- const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
188
+ const [email, setEmail] = (0, import_react3.useState)("");
189
+ const [sent, setSent] = (0, import_react3.useState)(false);
190
+ const [error, setError] = (0, import_react3.useState)(null);
209
191
  const requestReset = async (e) => {
210
192
  e.preventDefault();
211
193
  setError(null);
212
- const trimmedEmail = email.trim();
213
- if (!trimmedEmail) {
214
- setError("Email is required.");
215
- return;
216
- }
217
- if (!isValidEmail(trimmedEmail)) {
218
- setError("Enter a valid email address.");
219
- return;
220
- }
221
194
  try {
222
195
  const url = makeURL(config.baseURL, config.endpoints.forgot);
223
196
  await httpJSON(url, {
224
197
  method: "POST",
225
- body: JSON.stringify({ email: trimmedEmail })
198
+ body: JSON.stringify({ email })
226
199
  });
227
200
  setSent(true);
228
201
  } catch (err) {
229
- const message = err instanceof Error ? err.message : "Failed to request reset";
230
- setError(message);
202
+ setError(err?.message || "Failed to request reset");
231
203
  }
232
204
  };
233
205
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
@@ -267,7 +239,6 @@ function PasswordResetScreen() {
267
239
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
268
240
  "label",
269
241
  {
270
- htmlFor: "afk-reset-email",
271
242
  style: {
272
243
  position: "absolute",
273
244
  top: sent ? "-18px" : "-10px",
@@ -284,7 +255,6 @@ function PasswordResetScreen() {
284
255
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
285
256
  "input",
286
257
  {
287
- id: "afk-reset-email",
288
258
  value: email,
289
259
  onChange: (e) => setEmail(e.target.value),
290
260
  type: "email",
@@ -347,8 +317,6 @@ function PasswordResetScreen() {
347
317
  error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
348
318
  "p",
349
319
  {
350
- role: "alert",
351
- "aria-live": "polite",
352
320
  style: {
353
321
  marginTop: 20,
354
322
  color: "crimson",
@@ -368,11 +336,11 @@ function PasswordResetScreen() {
368
336
  var import_jsx_runtime4 = require("react/jsx-runtime");
369
337
  function LoginScreen() {
370
338
  const { login } = useAuth();
371
- const [email, setEmail] = (0, import_react3.useState)("");
372
- const [password, setPassword] = (0, import_react3.useState)("");
373
- const [submitting, setSubmitting] = (0, import_react3.useState)(false);
374
- const [error, setError] = (0, import_react3.useState)(null);
375
- const [showReset, setShowReset] = (0, import_react3.useState)(false);
339
+ const [email, setEmail] = (0, import_react4.useState)("");
340
+ const [password, setPassword] = (0, import_react4.useState)("");
341
+ const [submitting, setSubmitting] = (0, import_react4.useState)(false);
342
+ const [error, setError] = (0, import_react4.useState)(null);
343
+ const [showReset, setShowReset] = (0, import_react4.useState)(false);
376
344
  if (showReset) {
377
345
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { animation: "fade .2s" }, children: [
378
346
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PasswordResetScreen, {}),
@@ -399,26 +367,15 @@ function LoginScreen() {
399
367
  setError(null);
400
368
  const trimmedEmail = email.trim();
401
369
  const trimmedPassword = password.trim();
402
- if (!trimmedEmail) {
403
- setError("Email is required.");
404
- setSubmitting(false);
405
- return;
406
- }
407
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
408
- setError("Enter a valid email address.");
409
- setSubmitting(false);
410
- return;
411
- }
412
- if (!trimmedPassword) {
413
- setError("Password is required.");
370
+ if (!trimmedEmail || !trimmedPassword) {
371
+ setError("Email and password cannot be empty.");
414
372
  setSubmitting(false);
415
373
  return;
416
374
  }
417
375
  try {
418
376
  await login(trimmedEmail, trimmedPassword);
419
377
  } catch (err) {
420
- const message = err instanceof Error ? err.message : "Login failed";
421
- setError(message);
378
+ setError(err?.message || "Login failed");
422
379
  } finally {
423
380
  setSubmitting(false);
424
381
  }
@@ -459,7 +416,6 @@ function LoginScreen() {
459
416
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
460
417
  "label",
461
418
  {
462
- htmlFor: "afk-login-email",
463
419
  style: {
464
420
  position: "absolute",
465
421
  top: "-10px",
@@ -476,7 +432,6 @@ function LoginScreen() {
476
432
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
477
433
  "input",
478
434
  {
479
- id: "afk-login-email",
480
435
  value: email,
481
436
  onChange: (e) => setEmail(e.target.value),
482
437
  type: "email",
@@ -506,7 +461,6 @@ function LoginScreen() {
506
461
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
507
462
  "label",
508
463
  {
509
- htmlFor: "afk-login-password",
510
464
  style: {
511
465
  position: "absolute",
512
466
  top: "-10px",
@@ -523,7 +477,6 @@ function LoginScreen() {
523
477
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
524
478
  "input",
525
479
  {
526
- id: "afk-login-password",
527
480
  value: password,
528
481
  onChange: (e) => setPassword(e.target.value),
529
482
  type: "password",
@@ -550,28 +503,17 @@ function LoginScreen() {
550
503
  )
551
504
  ] }),
552
505
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
553
- "div",
506
+ "p",
554
507
  {
508
+ onClick: () => setShowReset(true),
555
509
  style: {
556
- textAlign: "right"
510
+ textAlign: "right",
511
+ fontSize: 13,
512
+ color: "#4b4bff",
513
+ cursor: "pointer",
514
+ marginBottom: 24
557
515
  },
558
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
559
- "button",
560
- {
561
- onClick: () => setShowReset(true),
562
- style: {
563
- textAlign: "right",
564
- fontSize: 13,
565
- color: "#4b4bff",
566
- cursor: "pointer",
567
- marginBottom: 24,
568
- width: "fit-content",
569
- border: "none",
570
- background: "none"
571
- },
572
- children: "Forgot password?"
573
- }
574
- )
516
+ children: "Forgot password?"
575
517
  }
576
518
  ),
577
519
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -599,8 +541,6 @@ function LoginScreen() {
599
541
  error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
600
542
  "p",
601
543
  {
602
- role: "alert",
603
- "aria-live": "polite",
604
544
  style: {
605
545
  marginTop: 18,
606
546
  color: "crimson",
@@ -617,28 +557,15 @@ function LoginScreen() {
617
557
  }
618
558
 
619
559
  // src/screens/SignupScreen.tsx
620
- var import_react4 = require("react");
560
+ var import_react5 = require("react");
621
561
  var import_jsx_runtime5 = require("react/jsx-runtime");
622
562
  function SignupScreen() {
623
563
  const { signup } = useAuth();
624
- const [name, setName] = (0, import_react4.useState)("");
625
- const [email, setEmail] = (0, import_react4.useState)("");
626
- const [password, setPassword] = (0, import_react4.useState)("");
627
- const [confirmPassword, setConfirmPassword] = (0, import_react4.useState)("");
628
- const [submitting, setSubmitting] = (0, import_react4.useState)(false);
629
- const [error, setError] = (0, import_react4.useState)(null);
630
- const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
631
- const getPasswordStrength = (value) => {
632
- let score = 0;
633
- if (value.length >= 8) score++;
634
- if (/[A-Z]/.test(value)) score++;
635
- if (/[0-9]/.test(value)) score++;
636
- if (/[^A-Za-z0-9]/.test(value)) score++;
637
- if (!value) return { label: "", color: "" };
638
- if (score <= 1) return { label: "Weak", color: "crimson" };
639
- if (score === 2) return { label: "Medium", color: "#f39c12" };
640
- return { label: "Strong", color: "#2ecc71" };
641
- };
564
+ const [name, setName] = (0, import_react5.useState)("");
565
+ const [email, setEmail] = (0, import_react5.useState)("");
566
+ const [password, setPassword] = (0, import_react5.useState)("");
567
+ const [submitting, setSubmitting] = (0, import_react5.useState)(false);
568
+ const [error, setError] = (0, import_react5.useState)(null);
642
569
  const onSubmit = async (e) => {
643
570
  e.preventDefault();
644
571
  setSubmitting(true);
@@ -646,47 +573,15 @@ function SignupScreen() {
646
573
  const trimmedEmail = email.trim();
647
574
  const trimmedPassword = password.trim();
648
575
  const trimmedName = name.trim();
649
- const trimmedConfirm = confirmPassword.trim();
650
- if (!trimmedName) {
651
- setError("Name is required.");
652
- setSubmitting(false);
653
- return;
654
- }
655
- if (!trimmedEmail) {
656
- setError("Email is required.");
657
- setSubmitting(false);
658
- return;
659
- }
660
- if (!isValidEmail(trimmedEmail)) {
661
- setError("Enter a valid email address.");
662
- setSubmitting(false);
663
- return;
664
- }
665
- if (!trimmedPassword) {
666
- setError("Password is required.");
667
- setSubmitting(false);
668
- return;
669
- }
670
- if (trimmedPassword.length < 8) {
671
- setError("Password must be at least 8 characters long.");
672
- setSubmitting(false);
673
- return;
674
- }
675
- if (!trimmedConfirm) {
676
- setError("Please confirm your password.");
677
- setSubmitting(false);
678
- return;
679
- }
680
- if (trimmedPassword !== trimmedConfirm) {
681
- setError("Passwords do not match.");
576
+ if (!trimmedEmail || !trimmedPassword || !trimmedName) {
577
+ setError("Email and password cannot be empty.");
682
578
  setSubmitting(false);
683
579
  return;
684
580
  }
685
581
  try {
686
- await signup({ name: trimmedName, email: trimmedEmail, password: trimmedPassword });
582
+ await signup({ name, email, password });
687
583
  } catch (err) {
688
- const message = err instanceof Error ? err.message : "Signup failed";
689
- setError(message);
584
+ setError(err?.message || "Signup failed");
690
585
  } finally {
691
586
  setSubmitting(false);
692
587
  }
@@ -728,7 +623,6 @@ function SignupScreen() {
728
623
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
729
624
  "label",
730
625
  {
731
- htmlFor: "afk-signup-name",
732
626
  style: {
733
627
  position: "absolute",
734
628
  top: "-10px",
@@ -745,7 +639,6 @@ function SignupScreen() {
745
639
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
746
640
  "input",
747
641
  {
748
- id: "afk-signup-name",
749
642
  value: name,
750
643
  onChange: (e) => setName(e.target.value),
751
644
  placeholder: "Your name",
@@ -774,7 +667,6 @@ function SignupScreen() {
774
667
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
775
668
  "label",
776
669
  {
777
- htmlFor: "afk-signup-email",
778
670
  style: {
779
671
  position: "absolute",
780
672
  top: "-10px",
@@ -791,7 +683,6 @@ function SignupScreen() {
791
683
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
792
684
  "input",
793
685
  {
794
- id: "afk-signup-email",
795
686
  value: email,
796
687
  onChange: (e) => setEmail(e.target.value),
797
688
  type: "email",
@@ -821,7 +712,6 @@ function SignupScreen() {
821
712
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
822
713
  "label",
823
714
  {
824
- htmlFor: "afk-signup-password",
825
715
  style: {
826
716
  position: "absolute",
827
717
  top: "-10px",
@@ -838,7 +728,6 @@ function SignupScreen() {
838
728
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
839
729
  "input",
840
730
  {
841
- id: "afk-signup-password",
842
731
  value: password,
843
732
  onChange: (e) => setPassword(e.target.value),
844
733
  type: "password",
@@ -864,95 +753,6 @@ function SignupScreen() {
864
753
  }
865
754
  )
866
755
  ] }),
867
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative", marginBottom: 18 }, children: [
868
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
869
- "label",
870
- {
871
- htmlFor: "afk-signup-confirm-password",
872
- style: {
873
- position: "absolute",
874
- top: "-10px",
875
- left: "14px",
876
- background: "rgba(255,255,255,0.85)",
877
- padding: "0 6px",
878
- fontSize: 13,
879
- color: "#444",
880
- borderRadius: 6
881
- },
882
- children: "Confirm password"
883
- }
884
- ),
885
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
886
- "input",
887
- {
888
- id: "afk-signup-confirm-password",
889
- value: confirmPassword,
890
- onChange: (e) => setConfirmPassword(e.target.value),
891
- type: "password",
892
- placeholder: "Repeat your password",
893
- style: {
894
- width: "80%",
895
- padding: "14px 16px",
896
- borderRadius: 12,
897
- border: "1px solid #d2d2d2",
898
- fontSize: 15,
899
- outline: "none",
900
- transition: "0.25s",
901
- background: "rgba(255,255,255,0.85)"
902
- },
903
- onFocus: (e) => {
904
- e.currentTarget.style.border = "1px solid #4b4bff";
905
- e.currentTarget.style.boxShadow = "0 0 0 3px rgba(75,75,255,0.25)";
906
- },
907
- onBlur: (e) => {
908
- e.currentTarget.style.border = "1px solid #d2d2d2";
909
- e.currentTarget.style.boxShadow = "0 0 0 transparent";
910
- }
911
- }
912
- )
913
- ] }),
914
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
915
- "div",
916
- {
917
- style: {
918
- marginBottom: 20,
919
- fontSize: 12,
920
- color: "#555"
921
- },
922
- children: [
923
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: { marginBottom: 6 }, children: "Use at least 8 characters, including letters, numbers, and symbols." }),
924
- password && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
925
- "p",
926
- {
927
- style: {
928
- fontWeight: 600,
929
- color: getPasswordStrength(password).color
930
- },
931
- children: [
932
- "Password strength: ",
933
- getPasswordStrength(password).label
934
- ]
935
- }
936
- )
937
- ]
938
- }
939
- ),
940
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
941
- "p",
942
- {
943
- style: {
944
- textAlign: "center",
945
- fontSize: 13,
946
- color: "#4b4bff",
947
- cursor: "pointer",
948
- marginBottom: 24
949
- },
950
- onClick: () => {
951
- window.dispatchEvent(new CustomEvent("auth-flow-kit:navigate-to-login"));
952
- },
953
- children: "Already have an account? Sign in"
954
- }
955
- ),
956
756
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
957
757
  "button",
958
758
  {
@@ -978,8 +778,6 @@ function SignupScreen() {
978
778
  error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
979
779
  "p",
980
780
  {
981
- role: "alert",
982
- "aria-live": "polite",
983
781
  style: {
984
782
  marginTop: 18,
985
783
  color: "crimson",