@githat/nextjs 0.4.0 → 0.4.2

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.mjs CHANGED
@@ -86,14 +86,21 @@ function createClient(apiUrl, appKey, options = {}) {
86
86
  });
87
87
  } catch (networkError) {
88
88
  if (networkError instanceof TypeError) {
89
- const isMissingKey = !appKey || !appKey.startsWith("pk_live_");
89
+ const isMissingKey = !appKey || !appKey.startsWith("pk_live_") && !appKey.startsWith("pk_test_");
90
90
  const isLocalhost = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
91
91
  if (isMissingKey && !isLocalhost) {
92
92
  throw new Error(
93
- "Missing GitHat API key. Add NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY to .env.local"
93
+ "GitHat: Missing or invalid publishable key. Add NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY to your environment variables. Get your key at https://githat.io/dashboard/apps"
94
94
  );
95
95
  }
96
- throw new Error("Unable to connect to GitHat API. Check your network connection.");
96
+ if (isLocalhost) {
97
+ throw new Error(
98
+ "GitHat: Cannot reach api.githat.io. Check your internet connection."
99
+ );
100
+ }
101
+ throw new Error(
102
+ "GitHat: API request failed. Verify your publishable key and app domain at https://githat.io/dashboard/apps"
103
+ );
97
104
  }
98
105
  throw networkError;
99
106
  }
@@ -129,12 +136,61 @@ function createClient(apiUrl, appKey, options = {}) {
129
136
  }
130
137
 
131
138
  // src/provider.tsx
132
- import { jsx } from "react/jsx-runtime";
139
+ import { jsx, jsxs } from "react/jsx-runtime";
133
140
  var GitHatContext = createContext(null);
141
+ function isDevMode(key) {
142
+ return !key || !key.startsWith("pk_live_") && !key.startsWith("pk_test_");
143
+ }
144
+ function DevModeBanner() {
145
+ const [dismissed, setDismissed] = useState(() => {
146
+ if (typeof window === "undefined") return true;
147
+ return localStorage.getItem("githat_dev_banner_dismissed") === "1";
148
+ });
149
+ if (dismissed || typeof window === "undefined") return null;
150
+ const hostname = window.location.hostname;
151
+ if (hostname !== "localhost" && hostname !== "127.0.0.1") return null;
152
+ return /* @__PURE__ */ jsxs("div", { className: "githat-dev-banner", role: "status", children: [
153
+ /* @__PURE__ */ jsxs("span", { children: [
154
+ /* @__PURE__ */ jsx("strong", { children: "GitHat Dev Mode" }),
155
+ " \u2014 No publishable key. Auth works on localhost.",
156
+ " ",
157
+ /* @__PURE__ */ jsx("a", { href: "https://githat.io/dashboard/apps", target: "_blank", rel: "noopener noreferrer", children: "Get your key" })
158
+ ] }),
159
+ /* @__PURE__ */ jsx(
160
+ "button",
161
+ {
162
+ onClick: () => {
163
+ setDismissed(true);
164
+ localStorage.setItem("githat_dev_banner_dismissed", "1");
165
+ },
166
+ "aria-label": "Dismiss",
167
+ children: "\xD7"
168
+ }
169
+ )
170
+ ] });
171
+ }
134
172
  function GitHatProvider({ config: rawConfig, children }) {
135
173
  const config = useMemo(() => resolveConfig(rawConfig), [rawConfig]);
136
174
  const useCookies = config.tokenStorage === "cookie";
175
+ const devMode = isDevMode(config.publishableKey);
137
176
  const clientRef = useRef(createClient(config.apiUrl, config.publishableKey, { useCookies }));
177
+ useEffect(() => {
178
+ if (!devMode || typeof window === "undefined") return;
179
+ const hostname = window.location.hostname;
180
+ if (hostname === "localhost" || hostname === "127.0.0.1") {
181
+ console.warn(
182
+ "%c GitHat Dev Mode %c No publishable key configured. Auth works on localhost but will fail in production. Get your key at https://githat.io/dashboard/apps",
183
+ "background: #f59e0b; color: #000; font-weight: bold; padding: 2px 6px; border-radius: 3px;",
184
+ "color: #f59e0b;"
185
+ );
186
+ } else {
187
+ console.error(
188
+ "%c GitHat %c Missing publishable key. Auth requests will fail. Add NEXT_PUBLIC_GITHAT_PUBLISHABLE_KEY to your environment. Get your key at https://githat.io/dashboard/apps",
189
+ "background: #ef4444; color: #fff; font-weight: bold; padding: 2px 6px; border-radius: 3px;",
190
+ "color: #ef4444;"
191
+ );
192
+ }
193
+ }, []);
138
194
  const [user, setUser] = useState(null);
139
195
  const [org, setOrg] = useState(null);
140
196
  const [isSignedIn, setIsSignedIn] = useState(false);
@@ -282,7 +338,10 @@ function GitHatProvider({ config: rawConfig, children }) {
282
338
  signOut,
283
339
  switchOrg
284
340
  }), [user, org, isSignedIn, isLoading, authError, config, signIn, signUp, signOut, switchOrg]);
285
- return /* @__PURE__ */ jsx(GitHatContext.Provider, { value, children });
341
+ return /* @__PURE__ */ jsxs(GitHatContext.Provider, { value, children: [
342
+ devMode && /* @__PURE__ */ jsx(DevModeBanner, {}),
343
+ children
344
+ ] });
286
345
  }
287
346
 
288
347
  // src/hooks.ts
@@ -323,13 +382,90 @@ function useGitHat() {
323
382
  },
324
383
  [client, ctx.org?.id]
325
384
  );
385
+ const forgotPassword = useCallback2(
386
+ async (email) => {
387
+ const response = await fetch(`${ctx.config.apiUrl}/auth/forgot-password`, {
388
+ method: "POST",
389
+ headers: { "Content-Type": "application/json" },
390
+ body: JSON.stringify({ email })
391
+ });
392
+ if (!response.ok) {
393
+ const error = await response.json().catch(() => ({}));
394
+ throw new Error(error.message || "Failed to send reset email");
395
+ }
396
+ return { success: true };
397
+ },
398
+ [ctx.config.apiUrl]
399
+ );
400
+ const resetPassword = useCallback2(
401
+ async (token, newPassword) => {
402
+ const response = await fetch(`${ctx.config.apiUrl}/auth/reset-password`, {
403
+ method: "POST",
404
+ headers: { "Content-Type": "application/json" },
405
+ body: JSON.stringify({ token, password: newPassword })
406
+ });
407
+ if (!response.ok) {
408
+ const error = await response.json().catch(() => ({}));
409
+ throw new Error(error.message || "Failed to reset password");
410
+ }
411
+ return { success: true };
412
+ },
413
+ [ctx.config.apiUrl]
414
+ );
415
+ const changePassword = useCallback2(
416
+ async (currentPassword, newPassword) => {
417
+ await client.fetchApi("/auth/change-password", {
418
+ method: "POST",
419
+ body: JSON.stringify({ currentPassword, newPassword })
420
+ });
421
+ return { success: true };
422
+ },
423
+ [client]
424
+ );
425
+ const verifyEmail = useCallback2(
426
+ async (token) => {
427
+ const response = await fetch(`${ctx.config.apiUrl}/auth/verify-email`, {
428
+ method: "POST",
429
+ headers: { "Content-Type": "application/json" },
430
+ body: JSON.stringify({ token })
431
+ });
432
+ if (!response.ok) {
433
+ const error = await response.json().catch(() => ({}));
434
+ throw new Error(error.message || "Failed to verify email");
435
+ }
436
+ return { success: true };
437
+ },
438
+ [ctx.config.apiUrl]
439
+ );
440
+ const resendVerificationEmail = useCallback2(
441
+ async (email) => {
442
+ const response = await fetch(`${ctx.config.apiUrl}/auth/resend-verification`, {
443
+ method: "POST",
444
+ headers: { "Content-Type": "application/json" },
445
+ body: JSON.stringify({ email })
446
+ });
447
+ if (!response.ok) {
448
+ const error = await response.json().catch(() => ({}));
449
+ throw new Error(error.message || "Failed to resend verification email");
450
+ }
451
+ return { success: true };
452
+ },
453
+ [ctx.config.apiUrl]
454
+ );
326
455
  return {
327
456
  fetch: client.fetchApi,
328
457
  getUserOrgs: () => client.fetchApi("/user/orgs"),
329
458
  verifyMCP: (domain) => client.fetchApi(`/verify/mcp/${domain}`),
330
459
  verifyAgent: (wallet) => client.fetchApi(`/verify/agent/${wallet}`),
331
460
  getOrgMetadata,
332
- updateOrgMetadata
461
+ updateOrgMetadata,
462
+ // Password management
463
+ forgotPassword,
464
+ resetPassword,
465
+ changePassword,
466
+ // Email verification
467
+ verifyEmail,
468
+ resendVerificationEmail
333
469
  };
334
470
  }
335
471
 
@@ -413,7 +549,7 @@ function useData() {
413
549
 
414
550
  // src/components/SignInForm.tsx
415
551
  import { useState as useState2 } from "react";
416
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
552
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
417
553
  function SignInForm({ onSuccess, signUpUrl, forgotPasswordUrl }) {
418
554
  const { signIn, config } = useAuth();
419
555
  const [email, setEmail] = useState2("");
@@ -443,14 +579,14 @@ function SignInForm({ onSuccess, signUpUrl, forgotPasswordUrl }) {
443
579
  setLoading(false);
444
580
  }
445
581
  };
446
- return /* @__PURE__ */ jsxs("div", { className: "githat-form-container", children: [
447
- /* @__PURE__ */ jsxs("div", { className: "githat-form-header", children: [
582
+ return /* @__PURE__ */ jsxs2("div", { className: "githat-form-container", children: [
583
+ /* @__PURE__ */ jsxs2("div", { className: "githat-form-header", children: [
448
584
  /* @__PURE__ */ jsx2("h2", { className: "githat-form-title", children: "Sign in" }),
449
585
  /* @__PURE__ */ jsx2("p", { className: "githat-form-subtitle", children: "Welcome back to GitHat" })
450
586
  ] }),
451
587
  error && /* @__PURE__ */ jsx2("div", { className: "githat-alert githat-alert-error", role: "alert", "aria-live": "polite", children: error }),
452
- /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "githat-form", "aria-label": "Sign in form", children: [
453
- /* @__PURE__ */ jsxs("div", { className: "githat-field", children: [
588
+ /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "githat-form", "aria-label": "Sign in form", children: [
589
+ /* @__PURE__ */ jsxs2("div", { className: "githat-field", children: [
454
590
  /* @__PURE__ */ jsx2("label", { className: "githat-label", htmlFor: "githat-signin-email", children: "Email" }),
455
591
  /* @__PURE__ */ jsx2(
456
592
  "input",
@@ -466,7 +602,7 @@ function SignInForm({ onSuccess, signUpUrl, forgotPasswordUrl }) {
466
602
  }
467
603
  )
468
604
  ] }),
469
- /* @__PURE__ */ jsxs("div", { className: "githat-field", children: [
605
+ /* @__PURE__ */ jsxs2("div", { className: "githat-field", children: [
470
606
  /* @__PURE__ */ jsx2("label", { className: "githat-label", htmlFor: "githat-signin-password", children: "Password" }),
471
607
  /* @__PURE__ */ jsx2(
472
608
  "input",
@@ -493,11 +629,11 @@ function SignInForm({ onSuccess, signUpUrl, forgotPasswordUrl }) {
493
629
  }
494
630
  )
495
631
  ] }),
496
- signUpUrl && /* @__PURE__ */ jsxs("p", { className: "githat-form-footer", children: [
632
+ signUpUrl && /* @__PURE__ */ jsxs2("p", { className: "githat-form-footer", children: [
497
633
  "Don't have an account? ",
498
634
  /* @__PURE__ */ jsx2("a", { href: signUpUrl, className: "githat-link", children: "Sign up" })
499
635
  ] }),
500
- /* @__PURE__ */ jsxs("p", { className: "githat-powered-by", children: [
636
+ /* @__PURE__ */ jsxs2("p", { className: "githat-powered-by", children: [
501
637
  "Secured by ",
502
638
  /* @__PURE__ */ jsx2("strong", { children: "GitHat" })
503
639
  ] })
@@ -506,7 +642,7 @@ function SignInForm({ onSuccess, signUpUrl, forgotPasswordUrl }) {
506
642
 
507
643
  // src/components/SignUpForm.tsx
508
644
  import { useState as useState3 } from "react";
509
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
645
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
510
646
  function SignUpForm({ onSuccess, signInUrl }) {
511
647
  const { signUp, config } = useAuth();
512
648
  const [name, setName] = useState3("");
@@ -541,14 +677,14 @@ function SignUpForm({ onSuccess, signInUrl }) {
541
677
  setLoading(false);
542
678
  }
543
679
  };
544
- return /* @__PURE__ */ jsxs2("div", { className: "githat-form-container", children: [
545
- /* @__PURE__ */ jsxs2("div", { className: "githat-form-header", children: [
680
+ return /* @__PURE__ */ jsxs3("div", { className: "githat-form-container", children: [
681
+ /* @__PURE__ */ jsxs3("div", { className: "githat-form-header", children: [
546
682
  /* @__PURE__ */ jsx3("h2", { className: "githat-form-title", children: "Create an account" }),
547
683
  /* @__PURE__ */ jsx3("p", { className: "githat-form-subtitle", children: "Get started with GitHat" })
548
684
  ] }),
549
685
  error && /* @__PURE__ */ jsx3("div", { className: "githat-alert githat-alert-error", role: "alert", "aria-live": "polite", children: error }),
550
- /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "githat-form", "aria-label": "Sign up form", children: [
551
- /* @__PURE__ */ jsxs2("div", { className: "githat-field", children: [
686
+ /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className: "githat-form", "aria-label": "Sign up form", children: [
687
+ /* @__PURE__ */ jsxs3("div", { className: "githat-field", children: [
552
688
  /* @__PURE__ */ jsx3("label", { className: "githat-label", htmlFor: "githat-signup-name", children: "Full name" }),
553
689
  /* @__PURE__ */ jsx3(
554
690
  "input",
@@ -564,7 +700,7 @@ function SignUpForm({ onSuccess, signInUrl }) {
564
700
  }
565
701
  )
566
702
  ] }),
567
- /* @__PURE__ */ jsxs2("div", { className: "githat-field", children: [
703
+ /* @__PURE__ */ jsxs3("div", { className: "githat-field", children: [
568
704
  /* @__PURE__ */ jsx3("label", { className: "githat-label", htmlFor: "githat-signup-email", children: "Email" }),
569
705
  /* @__PURE__ */ jsx3(
570
706
  "input",
@@ -580,7 +716,7 @@ function SignUpForm({ onSuccess, signInUrl }) {
580
716
  }
581
717
  )
582
718
  ] }),
583
- /* @__PURE__ */ jsxs2("div", { className: "githat-field", children: [
719
+ /* @__PURE__ */ jsxs3("div", { className: "githat-field", children: [
584
720
  /* @__PURE__ */ jsx3("label", { className: "githat-label", htmlFor: "githat-signup-password", children: "Password" }),
585
721
  /* @__PURE__ */ jsx3(
586
722
  "input",
@@ -607,11 +743,11 @@ function SignUpForm({ onSuccess, signInUrl }) {
607
743
  }
608
744
  )
609
745
  ] }),
610
- signInUrl && /* @__PURE__ */ jsxs2("p", { className: "githat-form-footer", children: [
746
+ signInUrl && /* @__PURE__ */ jsxs3("p", { className: "githat-form-footer", children: [
611
747
  "Already have an account? ",
612
748
  /* @__PURE__ */ jsx3("a", { href: signInUrl, className: "githat-link", children: "Sign in" })
613
749
  ] }),
614
- /* @__PURE__ */ jsxs2("p", { className: "githat-powered-by", children: [
750
+ /* @__PURE__ */ jsxs3("p", { className: "githat-powered-by", children: [
615
751
  "Secured by ",
616
752
  /* @__PURE__ */ jsx3("strong", { children: "GitHat" })
617
753
  ] })
@@ -638,7 +774,7 @@ function SignUpButton({ className, children, href }) {
638
774
 
639
775
  // src/components/UserButton.tsx
640
776
  import { useState as useState4, useRef as useRef2, useEffect as useEffect2 } from "react";
641
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
777
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
642
778
  function UserButton() {
643
779
  const { user, org, isSignedIn, signOut } = useAuth();
644
780
  const [open, setOpen] = useState4(false);
@@ -652,10 +788,10 @@ function UserButton() {
652
788
  }, []);
653
789
  if (!isSignedIn || !user) return null;
654
790
  const initials = user.name ? user.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : user.email[0].toUpperCase();
655
- return /* @__PURE__ */ jsxs3("div", { className: "githat-user-button", ref, children: [
791
+ return /* @__PURE__ */ jsxs4("div", { className: "githat-user-button", ref, children: [
656
792
  /* @__PURE__ */ jsx6("button", { className: "githat-avatar-trigger", onClick: () => setOpen(!open), "aria-label": "User menu", "aria-expanded": open, "aria-haspopup": "true", children: user.avatarUrl ? /* @__PURE__ */ jsx6("img", { src: user.avatarUrl, alt: user.name || "User avatar", className: "githat-avatar-img" }) : /* @__PURE__ */ jsx6("span", { className: "githat-avatar-initials", children: initials }) }),
657
- open && /* @__PURE__ */ jsxs3("div", { className: "githat-dropdown", role: "menu", children: [
658
- /* @__PURE__ */ jsxs3("div", { className: "githat-dropdown-header", children: [
793
+ open && /* @__PURE__ */ jsxs4("div", { className: "githat-dropdown", role: "menu", children: [
794
+ /* @__PURE__ */ jsxs4("div", { className: "githat-dropdown-header", children: [
659
795
  /* @__PURE__ */ jsx6("p", { className: "githat-dropdown-name", children: user.name }),
660
796
  /* @__PURE__ */ jsx6("p", { className: "githat-dropdown-email", children: user.email }),
661
797
  org && /* @__PURE__ */ jsx6("p", { className: "githat-dropdown-org", children: org.name })
@@ -671,7 +807,7 @@ function UserButton() {
671
807
 
672
808
  // src/components/OrgSwitcher.tsx
673
809
  import { useState as useState5, useEffect as useEffect3, useRef as useRef3 } from "react";
674
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
810
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
675
811
  function OrgSwitcher() {
676
812
  const { org, isSignedIn, switchOrg } = useAuth();
677
813
  const githat = useGitHat();
@@ -694,12 +830,12 @@ function OrgSwitcher() {
694
830
  return () => document.removeEventListener("mousedown", handleClickOutside);
695
831
  }, []);
696
832
  if (!isSignedIn || !org || orgs.length < 2 && !orgsLoading) return null;
697
- return /* @__PURE__ */ jsxs4("div", { className: "githat-org-switcher", ref, children: [
698
- /* @__PURE__ */ jsxs4("button", { className: "githat-org-trigger", onClick: () => setOpen(!open), "aria-label": "Switch organization", "aria-expanded": open, "aria-haspopup": "true", children: [
833
+ return /* @__PURE__ */ jsxs5("div", { className: "githat-org-switcher", ref, children: [
834
+ /* @__PURE__ */ jsxs5("button", { className: "githat-org-trigger", onClick: () => setOpen(!open), "aria-label": "Switch organization", "aria-expanded": open, "aria-haspopup": "true", children: [
699
835
  /* @__PURE__ */ jsx7("span", { className: "githat-org-name", children: org.name }),
700
836
  /* @__PURE__ */ jsx7("span", { className: "githat-chevron", children: open ? "\u25B2" : "\u25BC" })
701
837
  ] }),
702
- open && /* @__PURE__ */ jsx7("div", { className: "githat-dropdown", role: "menu", children: orgsLoading ? /* @__PURE__ */ jsx7("div", { className: "githat-dropdown-item", "aria-busy": "true", children: "Loading..." }) : orgs.map((o) => /* @__PURE__ */ jsxs4(
838
+ open && /* @__PURE__ */ jsx7("div", { className: "githat-dropdown", role: "menu", children: orgsLoading ? /* @__PURE__ */ jsx7("div", { className: "githat-dropdown-item", "aria-busy": "true", children: "Loading..." }) : orgs.map((o) => /* @__PURE__ */ jsxs5(
703
839
  "button",
704
840
  {
705
841
  className: `githat-dropdown-item ${o.id === org.id ? "githat-dropdown-item-active" : ""}`,
@@ -721,7 +857,7 @@ function OrgSwitcher() {
721
857
 
722
858
  // src/components/VerifiedBadge.tsx
723
859
  import { useState as useState6, useEffect as useEffect4, useRef as useRef4 } from "react";
724
- import { jsxs as jsxs5 } from "react/jsx-runtime";
860
+ import { jsxs as jsxs6 } from "react/jsx-runtime";
725
861
  var CACHE_TTL = 5 * 60 * 1e3;
726
862
  var cache = /* @__PURE__ */ new Map();
727
863
  function VerifiedBadge({ type, identifier, label }) {
@@ -750,7 +886,7 @@ function VerifiedBadge({ type, identifier, label }) {
750
886
  };
751
887
  }, [type, identifier]);
752
888
  if (verified === null) return null;
753
- return /* @__PURE__ */ jsxs5("span", { className: `githat-badge ${verified ? "githat-badge-verified" : "githat-badge-unverified"}`, children: [
889
+ return /* @__PURE__ */ jsxs6("span", { className: `githat-badge ${verified ? "githat-badge-verified" : "githat-badge-unverified"}`, children: [
754
890
  verified ? "\u2713" : "\u2717",
755
891
  " ",
756
892
  label || (verified ? "Verified" : "Unverified")
@@ -772,16 +908,409 @@ function ProtectedRoute({ children, fallback }) {
772
908
  }
773
909
  return /* @__PURE__ */ jsx8(Fragment, { children });
774
910
  }
911
+
912
+ // src/components/ForgotPasswordForm.tsx
913
+ import { useState as useState7 } from "react";
914
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
915
+ function ForgotPasswordForm({
916
+ onSuccess,
917
+ onError,
918
+ signInUrl = "/sign-in"
919
+ }) {
920
+ const { forgotPassword } = useGitHat();
921
+ const [email, setEmail] = useState7("");
922
+ const [isLoading, setIsLoading] = useState7(false);
923
+ const [sent, setSent] = useState7(false);
924
+ const [error, setError] = useState7("");
925
+ const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
926
+ const handleSubmit = async (e) => {
927
+ e.preventDefault();
928
+ if (!emailValid) {
929
+ setError("Please enter a valid email address");
930
+ return;
931
+ }
932
+ setIsLoading(true);
933
+ setError("");
934
+ try {
935
+ await forgotPassword(email);
936
+ setSent(true);
937
+ onSuccess?.(email);
938
+ } catch (err) {
939
+ const message = err instanceof Error ? err.message : "Failed to send reset email";
940
+ setError(message);
941
+ onError?.(err instanceof Error ? err : new Error(message));
942
+ } finally {
943
+ setIsLoading(false);
944
+ }
945
+ };
946
+ if (sent) {
947
+ return /* @__PURE__ */ jsxs7("div", { className: "githat-form-container", children: [
948
+ /* @__PURE__ */ jsxs7("div", { className: "githat-form-header", children: [
949
+ /* @__PURE__ */ jsx9("h2", { className: "githat-form-title", children: "Check your email" }),
950
+ /* @__PURE__ */ jsxs7("p", { className: "githat-form-subtitle", children: [
951
+ "We sent a password reset link to ",
952
+ /* @__PURE__ */ jsx9("strong", { children: email })
953
+ ] })
954
+ ] }),
955
+ /* @__PURE__ */ jsx9("a", { href: signInUrl, className: "githat-link", children: "Back to sign in" }),
956
+ /* @__PURE__ */ jsxs7("p", { className: "githat-powered-by", children: [
957
+ "Secured by ",
958
+ /* @__PURE__ */ jsx9("strong", { children: "GitHat" })
959
+ ] })
960
+ ] });
961
+ }
962
+ return /* @__PURE__ */ jsxs7("div", { className: "githat-form-container", children: [
963
+ /* @__PURE__ */ jsxs7("div", { className: "githat-form-header", children: [
964
+ /* @__PURE__ */ jsx9("h2", { className: "githat-form-title", children: "Forgot password" }),
965
+ /* @__PURE__ */ jsx9("p", { className: "githat-form-subtitle", children: "Enter your email and we'll send you a reset link" })
966
+ ] }),
967
+ error && /* @__PURE__ */ jsx9("div", { className: "githat-alert githat-alert-error", role: "alert", "aria-live": "polite", children: error }),
968
+ /* @__PURE__ */ jsxs7("form", { onSubmit: handleSubmit, className: "githat-form", "aria-label": "Forgot password form", children: [
969
+ /* @__PURE__ */ jsxs7("div", { className: "githat-field", children: [
970
+ /* @__PURE__ */ jsx9("label", { className: "githat-label", htmlFor: "githat-forgot-email", children: "Email" }),
971
+ /* @__PURE__ */ jsx9(
972
+ "input",
973
+ {
974
+ id: "githat-forgot-email",
975
+ className: "githat-input",
976
+ type: "email",
977
+ value: email,
978
+ onChange: (e) => setEmail(e.target.value),
979
+ placeholder: "you@example.com",
980
+ autoComplete: "email",
981
+ disabled: isLoading,
982
+ required: true
983
+ }
984
+ )
985
+ ] }),
986
+ /* @__PURE__ */ jsx9(
987
+ "button",
988
+ {
989
+ type: "submit",
990
+ className: "githat-button githat-button-primary",
991
+ disabled: isLoading || !email || email.length > 0 && !emailValid,
992
+ children: isLoading ? "Sending..." : "Send reset link"
993
+ }
994
+ )
995
+ ] }),
996
+ /* @__PURE__ */ jsxs7("p", { className: "githat-form-footer", children: [
997
+ "Remember your password? ",
998
+ /* @__PURE__ */ jsx9("a", { href: signInUrl, className: "githat-link", children: "Sign in" })
999
+ ] }),
1000
+ /* @__PURE__ */ jsxs7("p", { className: "githat-powered-by", children: [
1001
+ "Secured by ",
1002
+ /* @__PURE__ */ jsx9("strong", { children: "GitHat" })
1003
+ ] })
1004
+ ] });
1005
+ }
1006
+
1007
+ // src/components/ResetPasswordForm.tsx
1008
+ import { useState as useState8 } from "react";
1009
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1010
+ function ResetPasswordForm({
1011
+ token,
1012
+ onSuccess,
1013
+ onError,
1014
+ signInUrl = "/sign-in",
1015
+ minPasswordLength = 8
1016
+ }) {
1017
+ const { resetPassword } = useGitHat();
1018
+ const [password, setPassword] = useState8("");
1019
+ const [confirm, setConfirm] = useState8("");
1020
+ const [isLoading, setIsLoading] = useState8(false);
1021
+ const [success, setSuccess] = useState8(false);
1022
+ const [error, setError] = useState8("");
1023
+ const handleSubmit = async (e) => {
1024
+ e.preventDefault();
1025
+ if (password !== confirm) {
1026
+ setError("Passwords do not match");
1027
+ return;
1028
+ }
1029
+ if (password.length < minPasswordLength) {
1030
+ setError(`Password must be at least ${minPasswordLength} characters`);
1031
+ return;
1032
+ }
1033
+ setIsLoading(true);
1034
+ setError("");
1035
+ try {
1036
+ await resetPassword(token, password);
1037
+ setSuccess(true);
1038
+ onSuccess?.();
1039
+ } catch (err) {
1040
+ const message = err instanceof Error ? err.message : "Failed to reset password";
1041
+ setError(message);
1042
+ onError?.(err instanceof Error ? err : new Error(message));
1043
+ } finally {
1044
+ setIsLoading(false);
1045
+ }
1046
+ };
1047
+ if (success) {
1048
+ return /* @__PURE__ */ jsxs8("div", { className: "githat-form-container", children: [
1049
+ /* @__PURE__ */ jsxs8("div", { className: "githat-form-header", children: [
1050
+ /* @__PURE__ */ jsx10("h2", { className: "githat-form-title", children: "Password reset!" }),
1051
+ /* @__PURE__ */ jsx10("p", { className: "githat-form-subtitle", children: "Your password has been successfully reset." })
1052
+ ] }),
1053
+ /* @__PURE__ */ jsx10("a", { href: signInUrl, className: "githat-button githat-button-primary", style: { display: "block", textAlign: "center", textDecoration: "none" }, children: "Sign in" }),
1054
+ /* @__PURE__ */ jsxs8("p", { className: "githat-powered-by", children: [
1055
+ "Secured by ",
1056
+ /* @__PURE__ */ jsx10("strong", { children: "GitHat" })
1057
+ ] })
1058
+ ] });
1059
+ }
1060
+ return /* @__PURE__ */ jsxs8("div", { className: "githat-form-container", children: [
1061
+ /* @__PURE__ */ jsxs8("div", { className: "githat-form-header", children: [
1062
+ /* @__PURE__ */ jsx10("h2", { className: "githat-form-title", children: "Reset password" }),
1063
+ /* @__PURE__ */ jsx10("p", { className: "githat-form-subtitle", children: "Enter your new password" })
1064
+ ] }),
1065
+ error && /* @__PURE__ */ jsx10("div", { className: "githat-alert githat-alert-error", role: "alert", "aria-live": "polite", children: error }),
1066
+ /* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: "githat-form", "aria-label": "Reset password form", children: [
1067
+ /* @__PURE__ */ jsxs8("div", { className: "githat-field", children: [
1068
+ /* @__PURE__ */ jsx10("label", { className: "githat-label", htmlFor: "githat-reset-password", children: "New password" }),
1069
+ /* @__PURE__ */ jsx10(
1070
+ "input",
1071
+ {
1072
+ id: "githat-reset-password",
1073
+ className: "githat-input",
1074
+ type: "password",
1075
+ value: password,
1076
+ onChange: (e) => setPassword(e.target.value),
1077
+ placeholder: "Enter new password",
1078
+ autoComplete: "new-password",
1079
+ disabled: isLoading,
1080
+ required: true,
1081
+ minLength: minPasswordLength
1082
+ }
1083
+ )
1084
+ ] }),
1085
+ /* @__PURE__ */ jsxs8("div", { className: "githat-field", children: [
1086
+ /* @__PURE__ */ jsx10("label", { className: "githat-label", htmlFor: "githat-reset-confirm", children: "Confirm password" }),
1087
+ /* @__PURE__ */ jsx10(
1088
+ "input",
1089
+ {
1090
+ id: "githat-reset-confirm",
1091
+ className: "githat-input",
1092
+ type: "password",
1093
+ value: confirm,
1094
+ onChange: (e) => setConfirm(e.target.value),
1095
+ placeholder: "Confirm new password",
1096
+ autoComplete: "new-password",
1097
+ disabled: isLoading,
1098
+ required: true
1099
+ }
1100
+ )
1101
+ ] }),
1102
+ /* @__PURE__ */ jsx10(
1103
+ "button",
1104
+ {
1105
+ type: "submit",
1106
+ className: "githat-button githat-button-primary",
1107
+ disabled: isLoading || !password || !confirm,
1108
+ children: isLoading ? "Resetting..." : "Reset password"
1109
+ }
1110
+ )
1111
+ ] }),
1112
+ /* @__PURE__ */ jsxs8("p", { className: "githat-powered-by", children: [
1113
+ "Secured by ",
1114
+ /* @__PURE__ */ jsx10("strong", { children: "GitHat" })
1115
+ ] })
1116
+ ] });
1117
+ }
1118
+
1119
+ // src/components/VerifyEmailStatus.tsx
1120
+ import { useEffect as useEffect5, useState as useState9 } from "react";
1121
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1122
+ function VerifyEmailStatus({
1123
+ token,
1124
+ onSuccess,
1125
+ onError,
1126
+ signInUrl = "/sign-in",
1127
+ redirectDelay = 3e3
1128
+ }) {
1129
+ const { verifyEmail } = useGitHat();
1130
+ const [status, setStatus] = useState9("loading");
1131
+ const [error, setError] = useState9("");
1132
+ useEffect5(() => {
1133
+ if (!token) {
1134
+ setStatus("error");
1135
+ setError("Missing verification token");
1136
+ return;
1137
+ }
1138
+ verifyEmail(token).then(() => {
1139
+ setStatus("success");
1140
+ onSuccess?.();
1141
+ if (signInUrl && redirectDelay > 0) {
1142
+ setTimeout(() => {
1143
+ window.location.href = signInUrl;
1144
+ }, redirectDelay);
1145
+ }
1146
+ }).catch((err) => {
1147
+ setStatus("error");
1148
+ const message = err instanceof Error ? err.message : "Verification failed";
1149
+ setError(message);
1150
+ onError?.(err instanceof Error ? err : new Error(message));
1151
+ });
1152
+ }, [token, verifyEmail, onSuccess, onError, signInUrl, redirectDelay]);
1153
+ return /* @__PURE__ */ jsxs9("div", { className: "githat-form-container", children: [
1154
+ status === "loading" && /* @__PURE__ */ jsxs9("div", { className: "githat-form-header", children: [
1155
+ /* @__PURE__ */ jsx11("h2", { className: "githat-form-title", children: "Verifying email..." }),
1156
+ /* @__PURE__ */ jsx11("p", { className: "githat-form-subtitle", children: "Please wait while we verify your email address." })
1157
+ ] }),
1158
+ status === "success" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
1159
+ /* @__PURE__ */ jsxs9("div", { className: "githat-form-header", children: [
1160
+ /* @__PURE__ */ jsx11("h2", { className: "githat-form-title", children: "Email verified!" }),
1161
+ /* @__PURE__ */ jsx11("p", { className: "githat-form-subtitle", children: "Your email has been successfully verified. Redirecting to sign in..." })
1162
+ ] }),
1163
+ /* @__PURE__ */ jsx11("a", { href: signInUrl, className: "githat-button githat-button-primary", style: { display: "block", textAlign: "center", textDecoration: "none" }, children: "Sign in now" })
1164
+ ] }),
1165
+ status === "error" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
1166
+ /* @__PURE__ */ jsxs9("div", { className: "githat-form-header", children: [
1167
+ /* @__PURE__ */ jsx11("h2", { className: "githat-form-title", children: "Verification failed" }),
1168
+ /* @__PURE__ */ jsx11("p", { className: "githat-form-subtitle", children: error })
1169
+ ] }),
1170
+ /* @__PURE__ */ jsxs9("p", { className: "githat-form-footer", children: [
1171
+ "The link may have expired. ",
1172
+ /* @__PURE__ */ jsx11("a", { href: "/sign-up", className: "githat-link", children: "Try signing up again" })
1173
+ ] })
1174
+ ] }),
1175
+ /* @__PURE__ */ jsxs9("p", { className: "githat-powered-by", children: [
1176
+ "Secured by ",
1177
+ /* @__PURE__ */ jsx11("strong", { children: "GitHat" })
1178
+ ] })
1179
+ ] });
1180
+ }
1181
+
1182
+ // src/components/ChangePasswordForm.tsx
1183
+ import { useState as useState10 } from "react";
1184
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1185
+ function ChangePasswordForm({
1186
+ onSuccess,
1187
+ onError,
1188
+ minPasswordLength = 8
1189
+ }) {
1190
+ const { changePassword } = useGitHat();
1191
+ const [current, setCurrent] = useState10("");
1192
+ const [newPass, setNewPass] = useState10("");
1193
+ const [confirm, setConfirm] = useState10("");
1194
+ const [isLoading, setIsLoading] = useState10(false);
1195
+ const [error, setError] = useState10("");
1196
+ const [success, setSuccess] = useState10(false);
1197
+ const handleSubmit = async (e) => {
1198
+ e.preventDefault();
1199
+ if (newPass !== confirm) {
1200
+ setError("Passwords do not match");
1201
+ return;
1202
+ }
1203
+ if (newPass.length < minPasswordLength) {
1204
+ setError(`Password must be at least ${minPasswordLength} characters`);
1205
+ return;
1206
+ }
1207
+ setIsLoading(true);
1208
+ setError("");
1209
+ try {
1210
+ await changePassword(current, newPass);
1211
+ setSuccess(true);
1212
+ setCurrent("");
1213
+ setNewPass("");
1214
+ setConfirm("");
1215
+ onSuccess?.();
1216
+ } catch (err) {
1217
+ const message = err instanceof Error ? err.message : "Failed to change password";
1218
+ setError(message);
1219
+ onError?.(err instanceof Error ? err : new Error(message));
1220
+ } finally {
1221
+ setIsLoading(false);
1222
+ }
1223
+ };
1224
+ return /* @__PURE__ */ jsxs10("div", { className: "githat-form-container", children: [
1225
+ /* @__PURE__ */ jsxs10("div", { className: "githat-form-header", children: [
1226
+ /* @__PURE__ */ jsx12("h2", { className: "githat-form-title", children: "Change password" }),
1227
+ /* @__PURE__ */ jsx12("p", { className: "githat-form-subtitle", children: "Update your account password" })
1228
+ ] }),
1229
+ success && /* @__PURE__ */ jsx12("div", { className: "githat-alert githat-alert-success", role: "status", "aria-live": "polite", children: "Password changed successfully!" }),
1230
+ error && /* @__PURE__ */ jsx12("div", { className: "githat-alert githat-alert-error", role: "alert", "aria-live": "polite", children: error }),
1231
+ /* @__PURE__ */ jsxs10("form", { onSubmit: handleSubmit, className: "githat-form", "aria-label": "Change password form", children: [
1232
+ /* @__PURE__ */ jsxs10("div", { className: "githat-field", children: [
1233
+ /* @__PURE__ */ jsx12("label", { className: "githat-label", htmlFor: "githat-change-current", children: "Current password" }),
1234
+ /* @__PURE__ */ jsx12(
1235
+ "input",
1236
+ {
1237
+ id: "githat-change-current",
1238
+ className: "githat-input",
1239
+ type: "password",
1240
+ value: current,
1241
+ onChange: (e) => setCurrent(e.target.value),
1242
+ placeholder: "Enter current password",
1243
+ autoComplete: "current-password",
1244
+ disabled: isLoading,
1245
+ required: true
1246
+ }
1247
+ )
1248
+ ] }),
1249
+ /* @__PURE__ */ jsxs10("div", { className: "githat-field", children: [
1250
+ /* @__PURE__ */ jsx12("label", { className: "githat-label", htmlFor: "githat-change-new", children: "New password" }),
1251
+ /* @__PURE__ */ jsx12(
1252
+ "input",
1253
+ {
1254
+ id: "githat-change-new",
1255
+ className: "githat-input",
1256
+ type: "password",
1257
+ value: newPass,
1258
+ onChange: (e) => setNewPass(e.target.value),
1259
+ placeholder: "Enter new password",
1260
+ autoComplete: "new-password",
1261
+ disabled: isLoading,
1262
+ required: true,
1263
+ minLength: minPasswordLength
1264
+ }
1265
+ )
1266
+ ] }),
1267
+ /* @__PURE__ */ jsxs10("div", { className: "githat-field", children: [
1268
+ /* @__PURE__ */ jsx12("label", { className: "githat-label", htmlFor: "githat-change-confirm", children: "Confirm new password" }),
1269
+ /* @__PURE__ */ jsx12(
1270
+ "input",
1271
+ {
1272
+ id: "githat-change-confirm",
1273
+ className: "githat-input",
1274
+ type: "password",
1275
+ value: confirm,
1276
+ onChange: (e) => setConfirm(e.target.value),
1277
+ placeholder: "Confirm new password",
1278
+ autoComplete: "new-password",
1279
+ disabled: isLoading,
1280
+ required: true
1281
+ }
1282
+ )
1283
+ ] }),
1284
+ /* @__PURE__ */ jsx12(
1285
+ "button",
1286
+ {
1287
+ type: "submit",
1288
+ className: "githat-button githat-button-primary",
1289
+ disabled: isLoading || !current || !newPass || !confirm,
1290
+ children: isLoading ? "Changing..." : "Change password"
1291
+ }
1292
+ )
1293
+ ] }),
1294
+ /* @__PURE__ */ jsxs10("p", { className: "githat-powered-by", children: [
1295
+ "Secured by ",
1296
+ /* @__PURE__ */ jsx12("strong", { children: "GitHat" })
1297
+ ] })
1298
+ ] });
1299
+ }
775
1300
  export {
1301
+ ChangePasswordForm,
1302
+ ForgotPasswordForm,
776
1303
  GitHatProvider,
777
1304
  OrgSwitcher,
778
1305
  ProtectedRoute,
1306
+ ResetPasswordForm,
779
1307
  SignInButton,
780
1308
  SignInForm,
781
1309
  SignUpButton,
782
1310
  SignUpForm,
783
1311
  UserButton,
784
1312
  VerifiedBadge,
1313
+ VerifyEmailStatus,
785
1314
  useAuth,
786
1315
  useData,
787
1316
  useGitHat