@insforge/react 0.4.0 → 0.4.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/atoms.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { AlertTriangle, Check, EyeOff, Eye, Loader2, CircleCheck } from 'lucide-react';
3
- import { createContext, useState, useRef, useEffect, useContext } from 'react';
4
- import { createClient } from '@insforge/sdk';
3
+ import { createContext, useState, useRef, useEffect, useCallback, useContext } from 'react';
4
+ import { useSearchParams } from 'react-router-dom';
5
+ import '@insforge/sdk';
5
6
 
6
7
  function AuthBranding() {
7
8
  return /* @__PURE__ */ jsxs("div", { className: "if-authBranding if-internal-ab4k9w", children: [
@@ -89,21 +90,12 @@ function AuthErrorBanner({ error }) {
89
90
  if (!error) {
90
91
  return null;
91
92
  }
92
- return /* @__PURE__ */ jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
93
- /* @__PURE__ */ jsx(
94
- AlertTriangle,
95
- {
96
- style: { width: "1.5rem", height: "1.5rem", flexShrink: 0, color: "#dc2626" }
97
- }
98
- ),
93
+ return /* @__PURE__ */ jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxs("div", { className: "if-errorBanner-content", children: [
94
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "if-errorBanner-icon" }),
99
95
  /* @__PURE__ */ jsx("span", { className: "if-errorBanner-text", children: error })
100
96
  ] }) });
101
97
  }
102
- function AuthFormField({
103
- label,
104
- id,
105
- ...props
106
- }) {
98
+ function AuthFormField({ label, id, ...props }) {
107
99
  return /* @__PURE__ */ jsxs("div", { className: "if-formField if-internal-f9n6p2", children: [
108
100
  /* @__PURE__ */ jsx("label", { htmlFor: id, className: "if-formField-label if-internal-l3k8m1", children: label }),
109
101
  /* @__PURE__ */ jsx("input", { id, className: "if-formField-input if-internal-i2v8k4", ...props })
@@ -230,14 +222,17 @@ function AuthSubmitButton({
230
222
  children,
231
223
  isLoading = false,
232
224
  confirmed = false,
233
- disabled = false
225
+ disabled = false,
226
+ type = "submit",
227
+ onClick
234
228
  }) {
235
229
  return /* @__PURE__ */ jsxs(
236
230
  "button",
237
231
  {
238
- type: "submit",
232
+ type,
239
233
  className: "if-submitButton if-internal-b8p3m4",
240
234
  disabled: disabled || isLoading || confirmed,
235
+ onClick,
241
236
  children: [
242
237
  isLoading && /* @__PURE__ */ jsx(Loader2, { className: "if-submitButton-icon if-submitButton-spinner", size: 20 }),
243
238
  confirmed && /* @__PURE__ */ jsx(CircleCheck, { className: "if-submitButton-icon", size: 20 }),
@@ -246,24 +241,16 @@ function AuthSubmitButton({
246
241
  }
247
242
  );
248
243
  }
249
- function AuthLink({
250
- text,
251
- linkText,
252
- href
253
- }) {
254
- const currentSearch = typeof window !== "undefined" ? window.location.search : "";
244
+ function AuthLink({ text, linkText, href }) {
245
+ const [searchParams] = useSearchParams();
246
+ const currentSearch = searchParams.toString();
255
247
  const finalHref = (() => {
256
248
  if (!currentSearch) {
257
249
  return href;
258
250
  }
259
251
  try {
260
252
  const url = new URL(href, window.location.origin);
261
- const currentParams = new URLSearchParams(currentSearch);
262
- currentParams.forEach((value, key) => {
263
- if (!url.searchParams.has(key)) {
264
- url.searchParams.set(key, value);
265
- }
266
- });
253
+ url.search = currentSearch;
267
254
  return url.pathname + url.search;
268
255
  } catch {
269
256
  return href;
@@ -628,28 +615,26 @@ function useInsforge() {
628
615
  }
629
616
  function AuthEmailVerificationStep({
630
617
  email,
631
- description,
632
618
  method = "code",
633
619
  onVerifyCode
634
620
  }) {
635
- const { baseUrl } = useInsforge();
636
- const [insforge] = useState(() => createClient({ baseUrl }));
621
+ const { sendVerificationEmail } = useInsforge();
637
622
  const [resendDisabled, setResendDisabled] = useState(true);
638
623
  const [resendCountdown, setResendCountdown] = useState(60);
639
624
  const [isSending, setIsSending] = useState(false);
640
625
  const [verificationCode, setVerificationCode] = useState("");
641
626
  const [isVerifying, setIsVerifying] = useState(false);
642
- const [verificationError, setVerificationError] = useState("");
643
627
  const defaultDescription = method === "code" ? "We've sent a 6-digit verification code to {email}. Please enter it below to verify your account. The code will expire in 10 minutes." : "We've sent a verification link to {email}. Please check your email and click the link to verify your account. The link will expire in 10 minutes.";
644
628
  useEffect(() => {
645
629
  const sendInitialEmail = async () => {
646
630
  try {
647
- await insforge.auth.sendVerificationEmail({ email });
648
- } catch {
631
+ await sendVerificationEmail(email);
632
+ } catch (error) {
633
+ console.error("Failed to send verification email:", error);
649
634
  }
650
635
  };
651
636
  void sendInitialEmail();
652
- }, [email, method, insforge.auth]);
637
+ }, [email, sendVerificationEmail]);
653
638
  useEffect(() => {
654
639
  if (resendCountdown > 0) {
655
640
  const timer = setInterval(() => {
@@ -668,9 +653,8 @@ function AuthEmailVerificationStep({
668
653
  setResendDisabled(true);
669
654
  setResendCountdown(60);
670
655
  setIsSending(true);
671
- setVerificationError("");
672
656
  try {
673
- await insforge.auth.sendVerificationEmail({ email });
657
+ await sendVerificationEmail(email);
674
658
  } catch {
675
659
  setResendDisabled(false);
676
660
  setResendCountdown(0);
@@ -678,126 +662,160 @@ function AuthEmailVerificationStep({
678
662
  setIsSending(false);
679
663
  }
680
664
  };
681
- const handleVerifyCode = async (code) => {
682
- if (!onVerifyCode) {
665
+ const handleSubmit = async () => {
666
+ if (!onVerifyCode || verificationCode.length !== 6) {
683
667
  return;
684
668
  }
685
669
  setIsVerifying(true);
686
- setVerificationError("");
687
670
  try {
688
- await onVerifyCode(code);
689
- } catch (error) {
690
- setVerificationError(
691
- error instanceof Error ? error.message : "Invalid verification code. Please try again."
692
- );
693
- setVerificationCode("");
671
+ await onVerifyCode(verificationCode);
694
672
  } finally {
695
673
  setIsVerifying(false);
674
+ setVerificationCode("");
696
675
  }
697
676
  };
698
- const displayDescription = description || defaultDescription;
699
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem", alignItems: "stretch" }, children: [
700
- /* @__PURE__ */ jsx("p", { className: "if-verificationCode-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
677
+ const displayDescription = defaultDescription;
678
+ const isLinkMethod = method === "link";
679
+ return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
680
+ /* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
701
681
  part,
702
682
  index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "if-verificationCode-email", children: email })
703
683
  ] }, index)) }),
704
- verificationError && /* @__PURE__ */ jsx("div", { className: "if-errorBanner if-internal-eb2m7k", children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
684
+ !isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
685
+ /* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
686
+ AuthVerificationCodeInput,
687
+ {
688
+ value: verificationCode,
689
+ onChange: setVerificationCode,
690
+ email,
691
+ disabled: isVerifying
692
+ }
693
+ ) }),
705
694
  /* @__PURE__ */ jsx(
706
- "svg",
695
+ AuthSubmitButton,
707
696
  {
708
- style: { width: "1.5rem", height: "1.5rem", flexShrink: 0, color: "#DC2626" },
709
- fill: "none",
710
- strokeLinecap: "round",
711
- strokeLinejoin: "round",
712
- strokeWidth: "2",
713
- viewBox: "0 0 24 24",
714
- stroke: "currentColor",
715
- children: /* @__PURE__ */ jsx("path", { d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" })
697
+ type: "button",
698
+ isLoading: isVerifying,
699
+ disabled: isVerifying || verificationCode.length !== 6,
700
+ onClick: () => {
701
+ void handleSubmit();
702
+ },
703
+ children: isVerifying ? "Verifying..." : "Verify Code"
716
704
  }
717
- ),
718
- /* @__PURE__ */ jsx("p", { className: "if-errorBanner-text", children: verificationError })
719
- ] }) }),
720
- method === "code" && /* @__PURE__ */ jsxs(
721
- "div",
722
- {
723
- style: {
724
- width: "100%",
725
- backgroundColor: "#F5F5F5",
726
- borderRadius: "0.5rem",
727
- padding: "1rem 1rem 1.5rem",
728
- display: "flex",
729
- flexDirection: "column",
730
- gap: "1rem"
731
- },
732
- children: [
733
- /* @__PURE__ */ jsx(
734
- AuthVerificationCodeInput,
735
- {
736
- value: verificationCode,
737
- onChange: setVerificationCode,
738
- email,
739
- disabled: isVerifying,
740
- onComplete: (code) => {
741
- void handleVerifyCode(code);
742
- }
743
- }
744
- ),
745
- isVerifying && /* @__PURE__ */ jsx(
746
- "p",
747
- {
748
- style: {
749
- fontSize: "0.875rem",
750
- color: "#828282",
751
- textAlign: "center",
752
- fontFamily: "var(--if-font-family)"
753
- },
754
- children: "Verifying..."
755
- }
756
- )
757
- ]
758
- }
759
- ),
760
- /* @__PURE__ */ jsxs(
761
- "div",
762
- {
763
- style: {
764
- width: "100%",
765
- fontSize: "0.875rem",
766
- textAlign: "center",
767
- color: "#828282",
768
- fontFamily: "var(--if-font-family)"
769
- },
770
- children: [
771
- "Didn't receive the email?",
772
- " ",
773
- /* @__PURE__ */ jsx(
774
- "button",
775
- {
776
- onClick: () => {
777
- void handleResend();
778
- },
779
- disabled: resendDisabled || isSending,
780
- style: {
781
- color: "#000",
782
- fontWeight: 500,
783
- transition: "all 0.2s",
784
- cursor: resendDisabled || isSending ? "not-allowed" : "pointer",
785
- background: "none",
786
- border: "none",
787
- padding: 0,
788
- textDecoration: resendDisabled || isSending ? "none" : "underline",
789
- opacity: resendDisabled || isSending ? 0.5 : 1,
790
- fontFamily: "var(--if-font-family)"
791
- },
792
- children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
793
- }
794
- )
795
- ]
796
- }
797
- )
705
+ )
706
+ ] }),
707
+ /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-resendContainer", children: [
708
+ "Didn't receive the email?",
709
+ " ",
710
+ /* @__PURE__ */ jsx(
711
+ "button",
712
+ {
713
+ onClick: () => {
714
+ void handleResend();
715
+ },
716
+ disabled: resendDisabled || isSending,
717
+ className: "if-verificationStep-resendButton",
718
+ children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
719
+ }
720
+ )
721
+ ] })
722
+ ] });
723
+ }
724
+ function AuthResetPasswordVerificationStep({
725
+ email,
726
+ method,
727
+ onVerifyCode,
728
+ onResendEmail
729
+ }) {
730
+ const [resendDisabled, setResendDisabled] = useState(true);
731
+ const [resendCountdown, setResendCountdown] = useState(60);
732
+ const [isSending, setIsSending] = useState(false);
733
+ const [verificationCode, setVerificationCode] = useState("");
734
+ const [isVerifying, setIsVerifying] = useState(false);
735
+ useEffect(() => {
736
+ if (resendCountdown > 0) {
737
+ const timer = setInterval(() => {
738
+ setResendCountdown((prev) => {
739
+ if (prev <= 1) {
740
+ setResendDisabled(false);
741
+ return 0;
742
+ }
743
+ return prev - 1;
744
+ });
745
+ }, 1e3);
746
+ return () => clearInterval(timer);
747
+ }
748
+ }, [resendCountdown]);
749
+ const handleResend = useCallback(async () => {
750
+ setResendDisabled(true);
751
+ setResendCountdown(60);
752
+ setIsSending(true);
753
+ try {
754
+ await onResendEmail();
755
+ } catch {
756
+ setResendDisabled(false);
757
+ setResendCountdown(0);
758
+ } finally {
759
+ setIsSending(false);
760
+ }
761
+ }, [onResendEmail]);
762
+ const handleSubmit = async () => {
763
+ if (!onVerifyCode || verificationCode.length !== 6) {
764
+ return;
765
+ }
766
+ setIsVerifying(true);
767
+ try {
768
+ await onVerifyCode(verificationCode);
769
+ } finally {
770
+ setIsVerifying(false);
771
+ setVerificationCode("");
772
+ }
773
+ };
774
+ const isLinkMethod = method === "link";
775
+ const description = isLinkMethod ? `We've sent a password reset link to ${email}. Please check your email and click the link to reset your password. The link will expire in 10 minutes.` : `We've sent a 6-digit verification code to ${email}. Please enter it below to reset your password. The code will expire in 10 minutes.`;
776
+ return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
777
+ /* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: description }),
778
+ !isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
779
+ /* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
780
+ AuthVerificationCodeInput,
781
+ {
782
+ value: verificationCode,
783
+ onChange: setVerificationCode,
784
+ email,
785
+ disabled: isVerifying
786
+ }
787
+ ) }),
788
+ /* @__PURE__ */ jsx(
789
+ AuthSubmitButton,
790
+ {
791
+ type: "button",
792
+ isLoading: isVerifying,
793
+ disabled: isVerifying || verificationCode.length !== 6,
794
+ onClick: () => {
795
+ void handleSubmit();
796
+ },
797
+ children: isVerifying ? "Verifying..." : "Continue"
798
+ }
799
+ )
800
+ ] }),
801
+ /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-resendContainer", children: [
802
+ "Didn't receive the email?",
803
+ " ",
804
+ /* @__PURE__ */ jsx(
805
+ "button",
806
+ {
807
+ onClick: () => {
808
+ void handleResend();
809
+ },
810
+ disabled: resendDisabled || isSending,
811
+ className: "if-verificationStep-resendButton",
812
+ children: isSending ? "Sending..." : resendDisabled ? `Retry in (${resendCountdown}s)` : "Click to resend"
813
+ }
814
+ )
815
+ ] })
798
816
  ] });
799
817
  }
800
818
 
801
- export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthSubmitButton, AuthVerificationCodeInput };
819
+ export { AuthBranding, AuthContainer, AuthDivider, AuthEmailVerificationStep, AuthErrorBanner, AuthFormField, AuthHeader, AuthLink, AuthOAuthButton, AuthOAuthProviders, AuthPasswordField, AuthPasswordStrengthIndicator, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthVerificationCodeInput };
802
820
  //# sourceMappingURL=atoms.js.map
803
821
  //# sourceMappingURL=atoms.js.map