UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

291 lines (290 loc) 11 kB
'use client'; import { jsx as t, jsxs as u } from "react/jsx-runtime"; import c from "react"; import { motion as L } from "framer-motion"; import { useOAuth as b } from "../../../hooks/use-oauth.js"; import { useMagicLink as E } from "../../../hooks/use-magic-link.js"; import { useOrganization as P } from "../../../hooks/use-organization.js"; import { LoadingSpinner as p } from "./loading-spinner.js"; import { ErrorBoundary as R } from "./error-boundary.js"; function S() { return typeof window > "u" ? new URLSearchParams() : new URLSearchParams(window.location.search); } function A() { if (typeof window > "u") return new URLSearchParams(); const e = window.location.hash; return new URLSearchParams(e.startsWith("#") ? e.slice(1) : e); } function v() { const e = S(); return A().forEach((a, n) => { e.has(n) || e.set(n, a); }), e; } function y() { const e = v(); if (e.has("code") && e.has("state")) return "oauth"; if (e.has("token") && e.has("type")) { const o = e.get("type"); if (o === "magic_link" || o === "email_verification") return "magic-link"; } return e.has("invitation_token") || e.has("invite") ? "invitation" : e.has("verification_token") || e.has("verify") ? "verification" : e.has("error") || e.has("error_description") ? "error" : null; } function T({ onSuccess: e, onError: o, successUrl: a, errorUrl: n }) { const { handleCallback: s } = b(), [f, h] = c.useState(!0), [d, l] = c.useState(null); return c.useEffect(() => { (async () => { try { const r = v(), i = r.get("code"), x = r.get("state"), k = r.get("provider") || "google", w = r.get("error"); if (w) { const N = r.get("error_description") || "OAuth authentication failed"; throw new Error(`OAuth Error: ${w} - ${N}`); } if (!i) throw new Error("No authorization code received from OAuth provider"); const m = await s(k, i, x); if (m.success) e?.(m), a ? window.location.href = a : (window.history.replaceState({}, document.title, window.location.pathname), window.location.href = "/dashboard"); else throw new Error(m.error || "OAuth authentication failed"); } catch (r) { const i = r instanceof Error ? r : new Error("OAuth processing failed"); l(i), o?.(i), n && setTimeout(() => { window.location.href = n; }, 3e3); } finally { h(!1); } })(); }, [s, e, o, a, n]), d ? /* @__PURE__ */ u("div", { className: "text-center", children: [ /* @__PURE__ */ u("div", { className: "text-danger-600 mb-4", children: [ /* @__PURE__ */ t("svg", { className: "w-12 h-12 mx-auto mb-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ t("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z" }) }), /* @__PURE__ */ t("h3", { className: "text-lg font-semibold", children: "Authentication Failed" }), /* @__PURE__ */ t("p", { className: "text-sm text-default-500 mt-2", children: d.message }) ] }), n && /* @__PURE__ */ t("p", { className: "text-xs text-default-400", children: "Redirecting to sign in page..." }) ] }) : /* @__PURE__ */ t( p, { variant: "spinner", size: "lg", showText: !0, text: "Completing sign in...", centered: !0 } ); } function _({ onSuccess: e, onError: o, successUrl: a, errorUrl: n }) { const { verifyFromUrl: s } = E(), [f, h] = c.useState(!0), [d, l] = c.useState(null); return c.useEffect(() => { (async () => { try { const r = await s(); if (r.success) { if (e?.(r), r.requiresAdditionalVerification) { const i = new URLSearchParams(); i.set("mfa_token", r.mfaToken || ""), window.location.href = `/auth/mfa?${i.toString()}`; return; } a ? window.location.href = a : (window.history.replaceState({}, document.title, window.location.pathname), window.location.href = "/dashboard"); } else throw new Error(r.error || "Magic link verification failed"); } catch (r) { const i = r instanceof Error ? r : new Error("Magic link processing failed"); l(i), o?.(i), n && setTimeout(() => { window.location.href = n; }, 3e3); } finally { h(!1); } })(); }, [s, e, o, a, n]), d ? /* @__PURE__ */ u("div", { className: "text-center", children: [ /* @__PURE__ */ u("div", { className: "text-danger-600 mb-4", children: [ /* @__PURE__ */ t("svg", { className: "w-12 h-12 mx-auto mb-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ t("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z" }) }), /* @__PURE__ */ t("h3", { className: "text-lg font-semibold", children: "Verification Failed" }), /* @__PURE__ */ t("p", { className: "text-sm text-default-500 mt-2", children: d.message }) ] }), n && /* @__PURE__ */ t("p", { className: "text-xs text-default-400", children: "Redirecting to sign in page..." }) ] }) : /* @__PURE__ */ t( p, { variant: "pulse", size: "lg", showText: !0, text: "Verifying magic link...", centered: !0 } ); } function M({ onSuccess: e, onError: o, successUrl: a, errorUrl: n }) { const { acceptInvitation: s } = P(), [f, h] = c.useState(!0), [d, l] = c.useState(null); return c.useEffect(() => { (async () => { try { const r = v(), i = r.get("invitation_token") || r.get("invite"); if (!i) throw new Error("No invitation token found"); await s(i), e?.({ invitationToken: i }), a ? window.location.href = a : (window.history.replaceState({}, document.title, window.location.pathname), window.location.href = "/dashboard"); } catch (r) { const i = r instanceof Error ? r : new Error("Invitation processing failed"); l(i), o?.(i), n && setTimeout(() => { window.location.href = n; }, 3e3); } finally { h(!1); } })(); }, [s, e, o, a, n]), d ? /* @__PURE__ */ u("div", { className: "text-center", children: [ /* @__PURE__ */ u("div", { className: "text-danger-600 mb-4", children: [ /* @__PURE__ */ t("svg", { className: "w-12 h-12 mx-auto mb-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ t("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z" }) }), /* @__PURE__ */ t("h3", { className: "text-lg font-semibold", children: "Invitation Failed" }), /* @__PURE__ */ t("p", { className: "text-sm text-default-500 mt-2", children: d.message }) ] }), n && /* @__PURE__ */ t("p", { className: "text-xs text-default-400", children: "Redirecting to sign in page..." }) ] }) : /* @__PURE__ */ t( p, { variant: "dots", size: "lg", showText: !0, text: "Processing invitation...", centered: !0 } ); } function O({ type: e = "auto", successUrl: o, errorUrl: a, onSuccess: n, onError: s, loadingComponent: f, errorComponent: h, showLoading: d = !0, loadingText: l = "Processing...", className: g = "", children: r }) { const i = e === "auto" ? y() : e; if (!i && !r) return null; if (r) return /* @__PURE__ */ t("div", { className: g, children: r }); const x = d ? f || /* @__PURE__ */ t("div", { className: "flex items-center justify-center min-h-64", children: /* @__PURE__ */ t( p, { variant: "spinner", size: "lg", showText: !0, text: l, centered: !0 } ) }) : null, k = () => { switch (i) { case "oauth": return /* @__PURE__ */ t( T, { onSuccess: n, onError: s, successUrl: o, errorUrl: a } ); case "magic-link": return /* @__PURE__ */ t( _, { onSuccess: n, onError: s, successUrl: o, errorUrl: a } ); case "invitation": return /* @__PURE__ */ t( M, { onSuccess: n, onError: s, successUrl: o, errorUrl: a } ); case "error": const w = v(), m = w.get("error_description") || w.get("error") || "An error occurred", N = new Error(m); return h ? /* @__PURE__ */ t(h, { error: N, retry: () => window.location.reload() }) : /* @__PURE__ */ u("div", { className: "text-center", children: [ /* @__PURE__ */ u("div", { className: "text-danger-600 mb-4", children: [ /* @__PURE__ */ t("svg", { className: "w-12 h-12 mx-auto mb-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ t("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z" }) }), /* @__PURE__ */ t("h3", { className: "text-lg font-semibold", children: "Authentication Error" }), /* @__PURE__ */ t("p", { className: "text-sm text-default-500 mt-2", children: m }) ] }), a && /* @__PURE__ */ t("p", { className: "text-xs text-default-400", children: "Redirecting to sign in page..." }) ] }); default: return x; } }; return /* @__PURE__ */ t( L.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: `${g}`, children: /* @__PURE__ */ t( R, { title: "Redirect Processing Error", subtitle: "There was a problem processing the authentication redirect.", onError: s, showDetails: process.env.NODE_ENV === "development", children: k() } ) } ); } function V() { const [e, o] = c.useState(null), [a, n] = c.useState(!1), [s, f] = c.useState(null); c.useEffect(() => { const l = y(); o(l), n(!!l); }, []); const h = c.useCallback((l) => { n(!1), f(null); }, []), d = c.useCallback((l) => { n(!1), f(l); }, []); return { redirectType: e, isProcessing: a, error: s, handleSuccess: h, handleError: d, hasRedirect: !!e }; } var $ = O; export { O as RedirectHandler, $ as default, V as useRedirectHandler }; //# sourceMappingURL=redirect-handler.js.map