@insforge/react 0.4.6 → 0.4.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.
@@ -1,4 +1,4 @@
1
- import { createContext, useState, useRef, useEffect, useCallback, useContext } from 'react';
1
+ import { createContext, useState, useMemo, useRef, useEffect, useCallback, useContext } from 'react';
2
2
  import { useSearchParams } from 'react-router-dom';
3
3
  import '@insforge/sdk';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -197,6 +197,28 @@ function createRequirements(config) {
197
197
  }
198
198
  return requirements;
199
199
  }
200
+
201
+ // src/lib/path-utils.ts
202
+ function resolveAuthPath(targetPath) {
203
+ if (typeof window === "undefined") {
204
+ return targetPath;
205
+ }
206
+ const currentPath = window.location.pathname;
207
+ if (currentPath.startsWith("/auth/")) {
208
+ if (targetPath.startsWith("/auth/")) {
209
+ return targetPath;
210
+ }
211
+ return `/auth${targetPath}`;
212
+ }
213
+ return targetPath;
214
+ }
215
+ function resolveAuthUrl(targetPath, searchParams) {
216
+ const resolvedPath = resolveAuthPath(targetPath);
217
+ if (!searchParams || searchParams.toString() === "") {
218
+ return resolvedPath;
219
+ }
220
+ return `${resolvedPath}?${searchParams.toString()}`;
221
+ }
200
222
  function AuthPasswordField({
201
223
  label,
202
224
  id,
@@ -209,6 +231,10 @@ function AuthPasswordField({
209
231
  }) {
210
232
  const [showPassword, setShowPassword] = useState(false);
211
233
  const [showStrength, setShowStrength] = useState(false);
234
+ const resolvedForgotPasswordHref = useMemo(
235
+ () => forgotPasswordLink ? resolveAuthPath(forgotPasswordLink.href) : void 0,
236
+ [forgotPasswordLink]
237
+ );
212
238
  const handleFocus = (e) => {
213
239
  if (showStrengthIndicator) {
214
240
  setShowStrength(true);
@@ -218,7 +244,7 @@ function AuthPasswordField({
218
244
  return /* @__PURE__ */ jsxs("div", { className: "if-passwordField if-internal-p5w9m7", children: [
219
245
  (label || forgotPasswordLink) && /* @__PURE__ */ jsxs("div", { className: "if-passwordField-labelRow", children: [
220
246
  /* @__PURE__ */ jsx("label", { htmlFor: id, className: "if-passwordField-label", children: label }),
221
- forgotPasswordLink && /* @__PURE__ */ jsx("a", { href: forgotPasswordLink.href, className: "if-passwordField-forgotLink", children: forgotPasswordLink.text || "Forget Password?" })
247
+ forgotPasswordLink && resolvedForgotPasswordHref && /* @__PURE__ */ jsx("a", { href: resolvedForgotPasswordHref, className: "if-passwordField-forgotLink", children: forgotPasswordLink.text || "Forget Password?" })
222
248
  ] }),
223
249
  /* @__PURE__ */ jsxs("div", { className: "if-passwordField-inputWrapper", children: [
224
250
  /* @__PURE__ */ jsx(
@@ -271,19 +297,7 @@ function AuthSubmitButton({
271
297
  }
272
298
  function AuthLink({ text, linkText, href }) {
273
299
  const [searchParams] = useSearchParams();
274
- const currentSearch = searchParams.toString();
275
- const finalHref = (() => {
276
- if (!currentSearch) {
277
- return href;
278
- }
279
- try {
280
- const url = new URL(href, window.location.origin);
281
- url.search = currentSearch;
282
- return url.pathname + url.search;
283
- } catch {
284
- return href;
285
- }
286
- })();
300
+ const finalHref = resolveAuthUrl(href, searchParams);
287
301
  return /* @__PURE__ */ jsxs("p", { className: "if-authLink if-internal-al5w9p", children: [
288
302
  text && /* @__PURE__ */ jsx("span", { className: "if-authLink-text", children: text }),
289
303
  text && " ",
@@ -557,7 +571,6 @@ function AuthOAuthProviders({
557
571
  function AuthVerificationCodeInput({
558
572
  length = 6,
559
573
  value,
560
- email,
561
574
  onChange,
562
575
  disabled = false,
563
576
  onComplete
@@ -605,33 +618,25 @@ function AuthVerificationCodeInput({
605
618
  }
606
619
  }
607
620
  };
608
- return /* @__PURE__ */ jsxs("div", { className: "if-verificationCode if-internal-vc8m4p", children: [
609
- /* @__PURE__ */ jsxs("p", { className: "if-verificationCode-description", children: [
610
- "We've sent a verification code to your inbox at",
611
- " ",
612
- /* @__PURE__ */ jsx("span", { className: "if-verificationCode-email", children: email }),
613
- ". Enter it below to proceed."
614
- ] }),
615
- /* @__PURE__ */ jsx("div", { className: "if-verificationCode-inputContainer", children: Array.from({ length }).map((_, index) => /* @__PURE__ */ jsx(
616
- "input",
617
- {
618
- ref: (el) => {
619
- inputRefs.current[index] = el;
620
- },
621
- type: "text",
622
- inputMode: "numeric",
623
- maxLength: 1,
624
- value: value[index] || "",
625
- onChange: (e) => handleChange(index, e.target.value),
626
- onKeyDown: (e) => handleKeyDown(index, e),
627
- onPaste: handlePaste,
628
- disabled,
629
- className: "if-verificationCode-input",
630
- autoComplete: "one-time-code"
621
+ return /* @__PURE__ */ jsx("div", { className: "if-verificationCode-inputContainer", children: Array.from({ length }).map((_, index) => /* @__PURE__ */ jsx(
622
+ "input",
623
+ {
624
+ ref: (el) => {
625
+ inputRefs.current[index] = el;
631
626
  },
632
- index
633
- )) })
634
- ] });
627
+ type: "text",
628
+ inputMode: "numeric",
629
+ maxLength: 1,
630
+ value: value[index] || "",
631
+ onChange: (e) => handleChange(index, e.target.value),
632
+ onKeyDown: (e) => handleKeyDown(index, e),
633
+ onPaste: handlePaste,
634
+ disabled,
635
+ className: "if-verificationCode-input",
636
+ autoComplete: "one-time-code"
637
+ },
638
+ index
639
+ )) });
635
640
  }
636
641
  function AuthEmailVerificationStep({
637
642
  email,
@@ -644,7 +649,8 @@ function AuthEmailVerificationStep({
644
649
  const [isSending, setIsSending] = useState(false);
645
650
  const [verificationCode, setVerificationCode] = useState("");
646
651
  const [isVerifying, setIsVerifying] = useState(false);
647
- 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.";
652
+ const isLinkMethod = method === "link";
653
+ const displayDescription = isLinkMethod ? "We have sent an email to {email}. Please check your email to confirm your account before signing in. The confirmation link expires in 10 minutes." : "We've sent a verification code to your inbox at {email}. Enter it below to proceed.";
648
654
  useEffect(() => {
649
655
  const sendInitialEmail = async () => {
650
656
  try {
@@ -694,23 +700,29 @@ function AuthEmailVerificationStep({
694
700
  setVerificationCode("");
695
701
  }
696
702
  };
697
- const displayDescription = defaultDescription;
698
- const isLinkMethod = method === "link";
699
703
  return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
700
- /* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
701
- part,
702
- index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "if-verificationCode-email", children: email })
703
- ] }, index)) }),
704
+ isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-descriptionContainer", children: [
705
+ /* @__PURE__ */ jsx("p", { className: "if-verificationStep-descriptionTitle", children: "Verify Your Email" }),
706
+ /* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
707
+ part,
708
+ index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "if-verificationLink-email", children: email })
709
+ ] }, index)) })
710
+ ] }),
704
711
  !isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
705
- /* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
706
- AuthVerificationCodeInput,
707
- {
708
- value: verificationCode,
709
- onChange: setVerificationCode,
710
- email,
711
- disabled: isVerifying
712
- }
713
- ) }),
712
+ /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeInputWrapper", children: [
713
+ /* @__PURE__ */ jsx("p", { className: "if-verificationStep-codeDescription", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
714
+ part,
715
+ index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "if-verificationCode-email", children: email })
716
+ ] }, index)) }),
717
+ /* @__PURE__ */ jsx(
718
+ AuthVerificationCodeInput,
719
+ {
720
+ value: verificationCode,
721
+ onChange: setVerificationCode,
722
+ disabled: isVerifying
723
+ }
724
+ )
725
+ ] }),
714
726
  /* @__PURE__ */ jsx(
715
727
  AuthSubmitButton,
716
728
  {
@@ -720,7 +732,7 @@ function AuthEmailVerificationStep({
720
732
  onClick: () => {
721
733
  void handleSubmit();
722
734
  },
723
- children: isVerifying ? "Verifying..." : "Verify Code"
735
+ children: isVerifying ? "Verifying..." : "Continue"
724
736
  }
725
737
  )
726
738
  ] }),
@@ -752,6 +764,8 @@ function AuthResetPasswordVerificationStep({
752
764
  const [isSending, setIsSending] = useState(false);
753
765
  const [verificationCode, setVerificationCode] = useState("");
754
766
  const [isVerifying, setIsVerifying] = useState(false);
767
+ const isLinkMethod = method === "link";
768
+ const displayDescription = isLinkMethod ? "We have sent an email to {email}. Please check your email to reset your password. The link expires in 10 minutes." : "We've sent a reset password code to your inbox at {email}. Enter it below to proceed.";
755
769
  useEffect(() => {
756
770
  if (resendCountdown > 0) {
757
771
  const timer = setInterval(() => {
@@ -791,17 +805,20 @@ function AuthResetPasswordVerificationStep({
791
805
  setVerificationCode("");
792
806
  }
793
807
  };
794
- const isLinkMethod = method === "link";
795
- 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.`;
796
808
  return /* @__PURE__ */ jsxs("div", { className: "if-verificationStep", children: [
797
- /* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: description }),
809
+ isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-descriptionContainer", children: [
810
+ /* @__PURE__ */ jsx("p", { className: "if-verificationStep-descriptionTitle", children: "Check Your Email" }),
811
+ /* @__PURE__ */ jsx("p", { className: "if-verificationStep-description", children: displayDescription.split("{email}").map((part, index, array) => /* @__PURE__ */ jsxs("span", { children: [
812
+ part,
813
+ index < array.length - 1 && /* @__PURE__ */ jsx("span", { className: "if-verificationLink-email", children: email })
814
+ ] }, index)) })
815
+ ] }),
798
816
  !isLinkMethod && /* @__PURE__ */ jsxs("div", { className: "if-verificationStep-codeContainer", children: [
799
817
  /* @__PURE__ */ jsx("div", { className: "if-verificationStep-codeInputWrapper", children: /* @__PURE__ */ jsx(
800
818
  AuthVerificationCodeInput,
801
819
  {
802
820
  value: verificationCode,
803
821
  onChange: setVerificationCode,
804
- email,
805
822
  disabled: isVerifying
806
823
  }
807
824
  ) }),
@@ -854,7 +871,7 @@ function SignInForm({
854
871
  passwordLabel = "Password",
855
872
  passwordPlaceholder = "\u2022\u2022\u2022\u2022\u2022\u2022",
856
873
  forgotPasswordText = "Forget Password?",
857
- forgotPasswordUrl,
874
+ forgotPasswordUrl = "/forgot-password",
858
875
  submitButtonText = "Sign In",
859
876
  loadingButtonText = "Signing in...",
860
877
  signUpText = "Don't have an account?",
@@ -865,13 +882,7 @@ function SignInForm({
865
882
  onVerifyCode
866
883
  }) {
867
884
  return /* @__PURE__ */ jsxs(AuthContainer, { children: [
868
- /* @__PURE__ */ jsx(
869
- AuthHeader,
870
- {
871
- title: showVerificationStep ? "Verify Your Email" : title,
872
- subtitle: showVerificationStep ? "" : subtitle
873
- }
874
- ),
885
+ /* @__PURE__ */ jsx(AuthHeader, { title, subtitle }),
875
886
  /* @__PURE__ */ jsx(AuthErrorBanner, { error: error || "" }),
876
887
  showVerificationStep ? /* @__PURE__ */ jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
877
888
  /* @__PURE__ */ jsx(
@@ -970,7 +981,7 @@ function SignIn({ onError, ...uiProps }) {
970
981
  async function handleVerifyCode(code) {
971
982
  setError("");
972
983
  try {
973
- const result = await verifyEmail(email, code);
984
+ const result = await verifyEmail(code, email);
974
985
  if (result?.error) {
975
986
  throw new Error(result.error.message || "Verification failed");
976
987
  }
@@ -1041,13 +1052,7 @@ function SignUpForm({
1041
1052
  onVerifyCode
1042
1053
  }) {
1043
1054
  return /* @__PURE__ */ jsxs(AuthContainer, { children: [
1044
- /* @__PURE__ */ jsx(
1045
- AuthHeader,
1046
- {
1047
- title: showVerificationStep ? "Verify Your Email" : title,
1048
- subtitle: showVerificationStep ? "" : subtitle
1049
- }
1050
- ),
1055
+ /* @__PURE__ */ jsx(AuthHeader, { title, subtitle }),
1051
1056
  /* @__PURE__ */ jsx(AuthErrorBanner, { error: error || "" }),
1052
1057
  showVerificationStep ? /* @__PURE__ */ jsx(AuthEmailVerificationStep, { email, onVerifyCode }) : /* @__PURE__ */ jsxs("form", { onSubmit, noValidate: true, className: "if-form if-internal-fm9k2p", children: [
1053
1058
  /* @__PURE__ */ jsx(
@@ -1197,7 +1202,7 @@ function SignUp({ onError, ...uiProps }) {
1197
1202
  async function handleVerifyCode(code) {
1198
1203
  setError("");
1199
1204
  try {
1200
- const result = await verifyEmail(email, code);
1205
+ const result = await verifyEmail(code, email);
1201
1206
  if (result?.error) {
1202
1207
  throw new Error(result.error.message || "Verification failed");
1203
1208
  }
@@ -1247,10 +1252,10 @@ function ForgotPasswordForm({
1247
1252
  error,
1248
1253
  loading = false,
1249
1254
  title = "Forgot Password?",
1250
- subtitle = "Enter your email address and we'll send you a code to reset your password.",
1255
+ subtitle = "Enter your email address and we'll send you a {method} to reset your password.",
1251
1256
  emailLabel = "Email",
1252
1257
  emailPlaceholder = "example@email.com",
1253
- submitButtonText = "Send Reset Code",
1258
+ submitButtonText = "Reset Password",
1254
1259
  loadingButtonText = "Sending...",
1255
1260
  backToSignInText = "Remember your password?",
1256
1261
  backToSignInUrl = "/sign-in",
@@ -1259,14 +1264,9 @@ function ForgotPasswordForm({
1259
1264
  onVerifyCode,
1260
1265
  onResendEmail
1261
1266
  }) {
1267
+ const displaySubtitle = subtitle.replace("{method}", resetPasswordMethod);
1262
1268
  return /* @__PURE__ */ jsxs(AuthContainer, { children: [
1263
- /* @__PURE__ */ jsx(
1264
- AuthHeader,
1265
- {
1266
- title: showVerificationStep ? resetPasswordMethod === "link" ? "Check Your Email" : "Enter Reset Code" : title,
1267
- subtitle: showVerificationStep ? "" : subtitle
1268
- }
1269
- ),
1269
+ /* @__PURE__ */ jsx(AuthHeader, { title, subtitle: displaySubtitle }),
1270
1270
  /* @__PURE__ */ jsx(AuthErrorBanner, { error: error || "" }),
1271
1271
  showVerificationStep ? /* @__PURE__ */ jsx(
1272
1272
  AuthResetPasswordVerificationStep,
@@ -1493,12 +1493,9 @@ function ForgotPassword({ onError, ...uiProps }) {
1493
1493
  const result = await resetPassword(resetToken, newPassword);
1494
1494
  if (result?.message) {
1495
1495
  setSuccess(true);
1496
- const signInUrl = new URL("/sign-in", window.location.origin);
1497
- searchParams.forEach((value, key) => {
1498
- signInUrl.searchParams.set(key, value);
1499
- });
1496
+ const signInUrl = resolveAuthUrl("/sign-in", searchParams);
1500
1497
  setTimeout(() => {
1501
- window.location.href = signInUrl.toString();
1498
+ window.location.href = signInUrl;
1502
1499
  }, 2e3);
1503
1500
  } else {
1504
1501
  const errorMessage = "Failed to reset password";
@@ -1916,23 +1913,24 @@ function Protect({
1916
1913
  onRedirect
1917
1914
  }) {
1918
1915
  const { isSignedIn, isLoaded, user } = useInsforge();
1916
+ const resolvedRedirectTo = useMemo(() => resolveAuthPath(redirectTo), [redirectTo]);
1919
1917
  useEffect(() => {
1920
1918
  if (isLoaded && !isSignedIn) {
1921
1919
  if (onRedirect) {
1922
- onRedirect(redirectTo);
1920
+ onRedirect(resolvedRedirectTo);
1923
1921
  } else {
1924
- window.location.href = redirectTo;
1922
+ window.location.href = resolvedRedirectTo;
1925
1923
  }
1926
1924
  } else if (isLoaded && isSignedIn && condition && user) {
1927
1925
  if (!condition(user)) {
1928
1926
  if (onRedirect) {
1929
- onRedirect(redirectTo);
1927
+ onRedirect(resolvedRedirectTo);
1930
1928
  } else {
1931
- window.location.href = redirectTo;
1929
+ window.location.href = resolvedRedirectTo;
1932
1930
  }
1933
1931
  }
1934
1932
  }
1935
- }, [isLoaded, isSignedIn, redirectTo, condition, user, onRedirect]);
1933
+ }, [isLoaded, isSignedIn, resolvedRedirectTo, condition, user, onRedirect]);
1936
1934
  if (!isLoaded) {
1937
1935
  return fallback || /* @__PURE__ */ jsx("div", { className: "insforge-loading", children: "Loading..." });
1938
1936
  }