@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
4 lines (3 loc) • 8.47 kB
JavaScript
'use client';
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime");require("@emotion/styled");const V=require("../../../ui/button/button.cjs"),z=require("../../../ui/card/card.cjs"),H=require("../../../ui/chip/chip.cjs"),F=require("../../../ui/modal/modal.cjs"),m=require("@heroicons/react/24/outline"),l=require("react"),O=require("../../../../hooks/use-auth.cjs"),W=require("../../../../hooks/use-config.cjs"),C=require("../../common/error-boundary.cjs"),T=require("../../common/verification.cjs");function G({phoneNumber:s,userId:r,organizationId:i,autoSubmit:t=!0,codeLength:o=6,resendDelay:d=30,maxResendAttempts:f=3,expirationTime:h=300,onVerificationSuccess:y,onVerificationError:g,onCodeSent:E,onCodeResent:B}){const{client:p}=O.useAuth(),[x,k]=l.useState(""),[v,j]=l.useState("idle"),[q,u]=l.useState(null),[c,P]=l.useState(0),[w,N]=l.useState(0),[S,b]=l.useState(null);l.useEffect(()=>{if(w>0){const n=setTimeout(()=>N(a=>a-1),1e3);return()=>clearTimeout(n)}},[w]),l.useEffect(()=>{if(S){const a=setInterval(()=>{new Date>S&&(j("expired"),u("Verification code has expired"))},1e3);return()=>clearInterval(a)}},[S]),l.useEffect(()=>{t&&x.length===o&&v==="sent"&&$()},[x,o,t,v]);const M=l.useCallback(async()=>{if(!s||!r||!i){u("Missing required parameters for phone verification");return}try{j("sending"),u(null);const n=await p.mfa.sendSMSCode({orgId:i,userId:r});if(n.success)j("sent"),N(d),b(new Date(Date.now()+h*1e3)),E?.();else throw new Error(n.message||"Failed to send SMS verification code")}catch(n){const a=n instanceof Error?n:new Error("Failed to send SMS verification code");j("error"),u(a.message),g?.(a)}},[s,r,i,p,d,h,E,g]),D=l.useCallback(async()=>{if(c>=f){u("Maximum resend attempts reached");return}try{P(n=>n+1),await M(),B?.(c+1)}catch(n){const a=n instanceof Error?n:new Error("Failed to resend SMS code");g?.(a)}},[c,f,M,B,g]),$=l.useCallback(async()=>{if(!x||x.length!==o){u("Please enter a valid verification code");return}if(!s){u("Phone number is required for verification");return}try{if(j("verifying"),u(null),(await p.authentication.verifyPhone({verificationRequest:{phoneNumber:s,code:x}})).verified)j("verified"),y?.({phoneNumber:s||"",verified:!0});else throw new Error("Invalid verification code")}catch(n){const a=n instanceof Error?n:new Error("Phone verification failed");j("error"),u(a.message),g?.(a)}},[x,o,s,p,y,g]),A=l.useCallback(()=>{k(""),j("idle"),u(null),P(0),N(0),b(null)},[]);return{code:x,setCode:k,status:v,error:q,resendAttempts:c,timeRemaining:w,expiresAt:S,canResend:w===0&&c<f,sendCode:M,resendCode:D,handleVerify:$,reset:A}}function J(s){const r=s.replace(/\D/g,"");return r.length===10?`(${r.slice(0,3)}) ${r.slice(3,6)}-${r.slice(6)}`:r.length===11&&r[0]==="1"?`+1 (${r.slice(1,4)}) ${r.slice(4,7)}-${r.slice(7)}`:s}function X(s){return J(s).replace(/(\d{3})-(\d{4})/,"***-$2")}const R=C.withErrorBoundary(function({phoneNumber:r,userId:i,organizationId:t,autoSubmit:o=!0,codeLength:d=6,resendDelay:f=30,maxResendAttempts:h=3,expirationTime:y=300,onVerificationSuccess:g,onVerificationError:E,onCodeSent:B,onCodeResent:p,className:x,style:k,disabled:v=!1}){const{config:j}=W.useConfig(),{code:q,setCode:u,status:c,error:P,resendAttempts:w,timeRemaining:N,canResend:S,sendCode:b,resendCode:M,handleVerify:D}=G({phoneNumber:r,userId:i,organizationId:t,autoSubmit:o,codeLength:d,resendDelay:f,maxResendAttempts:h,expirationTime:y,onVerificationSuccess:g,onVerificationError:E,onCodeSent:B,onCodeResent:p}),$=I=>{I.length<=d&&u(I)},A=I=>{I.preventDefault(),D()},n=r?X(r):"",a=()=>c==="verified"?e.jsxs("div",{className:"text-center py-8",children:[e.jsx(m.CheckCircleIcon,{className:"h-16 w-16 text-success mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"Phone Verified!"}),e.jsx("p",{className:"text-default-500",children:"Your phone number has been successfully verified."})]}):c==="expired"?e.jsxs("div",{className:"text-center py-8",children:[e.jsx(m.XCircleIcon,{className:"h-16 w-16 text-warning mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"Code Expired"}),e.jsx("p",{className:"text-default-500 mb-4",children:"The SMS verification code has expired. Please request a new one."}),e.jsx(V.Button,{color:"primary",onClick:b,disabled:v,startContent:e.jsx(m.ArrowPathIcon,{className:"h-4 w-4"}),children:"Send New Code"})]}):e.jsxs("form",{onSubmit:A,className:"space-y-4",children:[e.jsxs("div",{className:"text-center",children:[e.jsx(m.DevicePhoneMobileIcon,{className:"h-12 w-12 text-primary mx-auto mb-4"}),e.jsx("h3",{className:"text-lg font-semibold mb-2",children:"Verify Your Phone"}),e.jsxs("p",{className:"text-default-500 mb-4",children:["We've sent a verification code to ",n]})]}),P&&e.jsx(T.VerificationError,{error:P}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(T.VerificationInput,{value:q,onChange:$,length:d,disabled:v||c==="verifying",placeholder:"Enter SMS code",type:"tel"}),e.jsx(V.Button,{type:"submit",color:"primary",className:"w-full",isLoading:c==="verifying",disabled:v||q.length!==d||c==="verifying",children:c==="verifying"?"Verifying...":"Verify Phone"}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm text-default-500",children:"Didn't receive the code?"}),e.jsx(Y,{onResend:M,disabled:v||!S,remainingTime:N,attempt:w,maxAttempts:h})]})]}),c==="idle"&&e.jsx(V.Button,{color:"primary",variant:"flat",className:"w-full",onClick:b,disabled:v,isLoading:c==="sending",children:c==="sending"?"Sending...":"Send SMS Code"})]});return e.jsx("div",{className:x,style:k,children:a()})}),K=C.withErrorBoundary(function({showHeader:r=!0,showInstructions:i=!0,...t}){return e.jsxs("div",{className:"space-y-6",children:[r&&e.jsxs("div",{className:"text-center",children:[e.jsx("h2",{className:"text-2xl font-bold",children:"Phone Verification"}),i&&e.jsx("p",{className:"text-default-500 mt-2",children:"Please verify your phone number to continue"})]}),e.jsx(R,{...t})]})}),Q=C.withErrorBoundary(function({isOpen:r,onClose:i,isDismissable:t=!0,...o}){return e.jsxs(F.Modal,{isOpen:r,onClose:i,isDismissable:t,size:"md",classNames:{backdrop:"bg-gradient-to-t from-zinc-900 to-zinc-900/10 backdrop-opacity-20"},children:[e.jsx(F.ModalHeader,{className:"flex flex-col gap-1",children:"Phone Verification"}),e.jsx(F.ModalBody,{children:e.jsx(R,{...o})})]})}),U=C.withErrorBoundary(function({variant:r="shadow",radius:i="lg",...t}){return e.jsx(z.Card,{className:`max-w-md mx-auto ${t.className||""}`,variant:r,radius:i,children:e.jsx(z.CardBody,{className:"p-6",children:e.jsx(R,{...t})})})}),Z=C.withErrorBoundary(function({status:r,phoneNumber:i,onRetry:t,className:o}){const f=(()=>{const h=X(i);switch(r){case"sent":return{color:"primary",icon:e.jsx(m.DevicePhoneMobileIcon,{className:"h-4 w-4"}),message:`SMS code sent to ${h}`};case"verified":return{color:"success",icon:e.jsx(m.CheckCircleIcon,{className:"h-4 w-4"}),message:`Phone ${h} verified successfully`};case"error":return{color:"danger",icon:e.jsx(m.XCircleIcon,{className:"h-4 w-4"}),message:"SMS verification failed"};case"expired":return{color:"warning",icon:e.jsx(m.XCircleIcon,{className:"h-4 w-4"}),message:"SMS code expired"};default:return{color:"default",icon:e.jsx(m.DevicePhoneMobileIcon,{className:"h-4 w-4"}),message:"Phone verification"}}})();return e.jsxs("div",{className:`flex items-center justify-between p-3 rounded-lg ${o||""}`,children:[e.jsx("div",{className:"flex items-center gap-3",children:e.jsx(H.Chip,{color:f.color,variant:"flat",startContent:f.icon,children:f.message})}),(r==="error"||r==="expired")&&t&&e.jsx(V.Button,{size:"sm",color:"primary",variant:"flat",onClick:t,startContent:e.jsx(m.ArrowPathIcon,{className:"h-3 w-3"}),children:"Retry"})]})}),Y=C.withErrorBoundary(function({onResend:r,disabled:i=!1,remainingTime:t=0,attempt:o=0,maxAttempts:d=3,className:f}){const h=t===0&&o<d,y=d-o;return e.jsx(V.Button,{size:"sm",color:"primary",variant:"light",onClick:r,disabled:i||!h,className:f,startContent:h?e.jsx(m.ArrowPathIcon,{className:"h-3 w-3"}):void 0,children:t>0?`Resend in ${t}s`:o>=d?"Max attempts reached":`Resend SMS${o>0?` (${y} left)`:""}`})});exports.PhoneVerification=R;exports.PhoneVerificationCard=U;exports.PhoneVerificationForm=K;exports.PhoneVerificationModal=Q;exports.PhoneVerificationStatus=Z;exports.ResendSMSButton=Y;
//# sourceMappingURL=phone-verification.cjs.map