@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
123 lines (120 loc) • 12.6 kB
JavaScript
'use client';
;Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t=require("react/jsx-runtime"),we=require("@emotion/styled"),z=require("../ui/button/button.cjs"),je=require("../ui/input/input.cjs"),$e=require("../ui/chip/chip.cjs"),J=require("../ui/progress/progress.cjs"),Se=require("../../hooks/use-config.cjs"),F=require("../../theme/context.cjs"),q=require("@heroicons/react/24/outline"),w=require("framer-motion"),qe=require("react"),Ce=require("./field-error.cjs"),ve=require("./form-wrapper.cjs"),K=require("../auth/sign-up/index.cjs"),Q=e=>e&&e.__esModule?e:{default:e},n=Q(we),u=Q(qe),ke=n.default.div`
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[2]};
`,Pe=n.default(z.Button)`
color: ${e=>e.theme.colors.text.quaternary};
&:hover {
color: ${e=>e.theme.colors.text.tertiary};
}
`,R=n.default.svg`
width: ${e=>e.theme.spacing[4]};
height: ${e=>e.theme.spacing[4]};
color: ${e=>e.theme.colors.text.quaternary};
`,Y=n.default(w.motion.div)`
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[2]};
`,ee=n.default.div`
display: flex;
align-items: center;
justify-content: space-between;
font-size: ${e=>e.theme.fontSizes.sm};
`,Ie=n.default.span`
color: ${e=>e.theme.colors.text.secondary};
`,Le=n.default.span`
font-weight: ${e=>e.theme.fontWeights.medium};
color: ${e=>{switch(e.strengthColor){case"danger":return e.theme.colors.danger[500];case"warning":return e.theme.colors.warning[500];case"primary":return e.theme.colors.primary[500];case"success":return e.theme.colors.success[500];default:return e.theme.colors.text.primary}}};
`,ze=n.default.div`
font-size: ${e=>e.theme.fontSizes.xs};
color: ${e=>e.theme.colors.text.tertiary};
`,Re=n.default(w.motion.div)`
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[2]};
`,Fe=n.default.div`
font-size: ${e=>e.theme.fontSizes.sm};
font-weight: ${e=>e.theme.fontWeights.medium};
color: ${e=>e.theme.colors.text.primary};
`,Me=n.default.div`
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[1]};
`,Ae=n.default.div`
display: flex;
align-items: center;
gap: ${e=>e.theme.spacing[2]};
font-size: ${e=>e.theme.fontSizes.xs};
`,_e=n.default.div`
width: ${e=>e.theme.spacing[4]};
height: ${e=>e.theme.spacing[4]};
border-radius: ${e=>e.theme.borderRadius.full};
display: flex;
align-items: center;
justify-content: center;
background-color: ${e=>e.met?e.theme.colors.success[100]:e.theme.colors.background.tertiary};
color: ${e=>e.met?e.theme.colors.success[600]:e.theme.colors.text.quaternary};
`,Te=n.default.svg`
width: ${e=>e.theme.spacing[3]};
height: ${e=>e.theme.spacing[3]};
`,Oe=n.default.div`
width: 6px;
height: 6px;
border-radius: ${e=>e.theme.borderRadius.full};
background-color: currentColor;
`,Ee=n.default.span`
color: ${e=>e.met?e.theme.colors.success[600]:e.theme.colors.text.tertiary};
`,Ve=n.default.div`
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[2]};
`,We=n.default.div`
font-size: ${e=>e.theme.fontSizes.xs};
color: ${e=>e.theme.colors.text.tertiary};
`,Be=n.default.div`
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[1]};
`,Ne=n.default.button`
font-size: ${e=>e.theme.fontSizes.xs};
font-family: monospace;
color: ${e=>e.theme.colors.primary[600]};
background: none;
border: none;
cursor: pointer;
text-align: left;
padding: 0;
&:hover {
color: ${e=>e.theme.colors.primary[800]};
text-decoration: underline;
}
`,Ue=n.default.div`
font-size: ${e=>e.theme.fontSizes.xs};
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[1]};
`,Ge=n.default.div`
display: flex;
align-items: center;
gap: ${e=>e.theme.spacing[1]};
color: ${e=>e.theme.colors.text.tertiary};
`,Ze=n.default.svg`
width: ${e=>e.theme.spacing[3]};
height: ${e=>e.theme.spacing[3]};
`,De=n.default.div`
font-size: ${e=>e.theme.fontSizes.xs};
display: flex;
flex-direction: column;
gap: ${e=>e.theme.spacing[1]};
`,He=n.default.div`
display: flex;
align-items: center;
gap: ${e=>e.theme.spacing[1]};
color: ${e=>e.met?e.theme.colors.success[600]:e.theme.colors.text.quaternary};
`,Xe=n.default.svg`
width: ${e=>e.theme.spacing[3]};
height: ${e=>e.theme.spacing[3]};
opacity: ${e=>e.met?1:.3};
`,I={minLength:8,maxLength:128,requireUppercase:!0,requireLowercase:!0,requireNumbers:!0,requireSpecialChars:!0,preventCommon:!0,preventUserInfo:!1},Je=["password","123456","123456789","qwerty","abc123","password123","admin","letmein","welcome","monkey","1234567890","iloveyou"],L=/[!@#$%^&*()_+=\[\]{}|;':",./<>?~`-]/;function Ke(e,r,d){const c=[];let o=0;const h=[];if(r.minLength){const i=e.length>=r.minLength;c.push({id:"length",label:`At least ${r.minLength} characters`,met:i,required:!0}),i?o+=1:h.push(`Password must be at least ${r.minLength} characters long`)}if(r.requireUppercase){const i=/[A-Z]/.test(e);c.push({id:"uppercase",label:"One uppercase letter",met:i,required:!0}),i?o+=1:h.push("Password must contain at least one uppercase letter")}if(r.requireLowercase){const i=/[a-z]/.test(e);c.push({id:"lowercase",label:"One lowercase letter",met:i,required:!0}),i?o+=1:h.push("Password must contain at least one lowercase letter")}if(r.requireNumbers){const i=/\d/.test(e);c.push({id:"number",label:"One number",met:i,required:!0}),i?o+=1:h.push("Password must contain at least one number")}if(r.requireSpecialChars){const i=L.test(e);c.push({id:"special",label:"One special character",met:i,required:!0}),i?o+=1:h.push("Password must contain at least one special character (!@#$%^&*()_+-=[]{}|;':\",./<>?~`)")}if(r.preventCommon){const i=Je.includes(e.toLowerCase());c.push({id:"common",label:"Not a common password",met:!i,required:!1}),i&&(o=Math.max(0,o-2),h.push("This is a commonly used password"))}if(e.length>=12&&(o+=1),e.length>=16&&(o+=1),/[A-Z].*[A-Z]/.test(e)&&(o+=.5),/\d.*\d/.test(e)&&(o+=.5),L.test(e)){const i=e.match(new RegExp(L.source,"g"));i&&i.length>=2&&(o+=.5)}o=Math.min(4,Math.floor(o*.8));let l,m,g;switch(o){case 0:case 1:l="Very Weak",m="danger",g=20;break;case 2:l="Weak",m="warning",g=40;break;case 3:l="Good",m="primary",g=70;break;case 4:l="Strong",m="success",g=100;break;default:l="Very Weak",m="danger",g=0}return{score:o,label:l,color:m,percentage:g,feedback:h,requirements:c}}function te({name:e="password",label:r="Password",placeholder:d="Enter your password",value:c="",onChange:o,onBlur:h,onFocus:l,required:m=!1,disabled:g=!1,showStrength:i=!0,showRequirements:A=!1,showSuggestions:se=!1,enableGenerate:re=!1,allowToggle:_=!0,rules:y=I,size:T="md",radius:ne="md",variant:O="bordered",className:E="",autoFocus:V=!1,autoComplete:W="current-password",isConfirmation:$=!1,originalPassword:S,error:b,description:B,startContent:oe,advanceRequirements:N}){const{theme:a}=F.useTheme(),{components:C,organizationSettings:U}=Se.useConfig(),f=ve.useFormField(e),ie=C.Input??je.Input;C.Button??z.Button;const G=C.PasswordField;if(G)return t.jsx(G,{name:e,label:r,placeholder:d,value:c,onChange:o,onBlur:h,onFocus:l,required:m,disabled:g,showStrength:i,showRequirements:A,allowToggle:_,rules:y,size:T,variant:O,className:E,autoFocus:V,autoComplete:W,isConfirmation:$,originalPassword:S,error:b,description:B});const[ae,ce]=u.default.useState(c),[v,le]=u.default.useState(!1),[Z,D]=u.default.useState(!1),[H,ue]=u.default.useState([]),p=o?c:ae,X=u.default.useMemo(()=>{const s=U?.passwordPolicy;return s?{...I,...y,minLength:s.minLength||y.minLength,requireUppercase:s.requireUppercase??y.requireUppercase,requireLowercase:s.requireLowercase??y.requireLowercase,requireNumbers:s.requireNumbers??y.requireNumbers,requireSpecialChars:s.requireSpecialChars??y.requireSpecialChars}:{...I,...y}},[y,U]),x=u.default.useMemo(()=>p?Ke(p,X):null,[p,X]),k=u.default.useMemo(()=>!$||!S||!p?null:S!==p?"Passwords do not match":null,[$,S,p]),P=u.default.useMemo(()=>{const s=[];return b&&(Array.isArray(b)?s.push(...b):s.push(b)),f.error&&(Array.isArray(f.error)?s.push(...f.error):s.push(f.error)),k&&s.push(k),s.length>0?s:null},[b,f.error,k]),de=u.default.useCallback(s=>{o?o(s):ce(s),f.clearError&&f.clearError()},[o,f]),he=u.default.useCallback(()=>{D(!1),f.setTouched&&f.setTouched(!0),h?.()},[f,h]),me=u.default.useCallback(()=>{D(!0),l?.()},[l]),fe=u.default.useCallback(()=>{le(s=>!s)},[]),ge=A&&(Z||p),pe=se&&(Z||p),xe=i&&p&&!$,ye=u.default.useCallback(()=>{const s=K.generatePasswordSuggestions();ue(s)},[]);return t.jsxs(ke,{theme:a,className:E,children:[t.jsx(ie,{name:e,label:r,placeholder:d,value:p,onBlur:he,onFocus:me,type:v?"text":"password",isRequired:m,isDisabled:g,onChange:s=>de(typeof s=="string"?s:s.target.value),required:m,disabled:g,size:T,radius:ne,variant:O,autoFocus:V,autoComplete:W,description:B,isInvalid:!!P,errorMessage:"",startContent:oe,endContent:_&&t.jsx(Pe,{theme:a,isIconOnly:!0,variant:"ghost",size:"sm",type:"button",color:"secondary",onClick:fe,"aria-label":v?"Hide password":"Show password",children:v?t.jsx(R,{theme:a,as:q.EyeSlashIcon}):t.jsx(R,{theme:a,as:q.EyeIcon})})}),P&&t.jsx(Ce.FieldError,{error:P,fieldName:e}),t.jsx(w.AnimatePresence,{children:xe&&x&&t.jsxs(Y,{theme:a,initial:{opacity:0,height:0},animate:{opacity:1,height:"auto"},exit:{opacity:0,height:0},children:[t.jsxs(ee,{theme:a,children:[t.jsx(Ie,{theme:a,children:"Password strength:"}),t.jsx(Le,{theme:a,strengthColor:x.color,children:x.label})]}),t.jsx(J.Progress,{value:x.percentage,color:x.color,size:"xs"}),x.feedback.length>0&&t.jsx(ze,{theme:a,children:x.feedback[0]})]})}),t.jsx(w.AnimatePresence,{children:ge&&x&&t.jsx(Re,{theme:a,initial:{opacity:0,height:0},animate:{opacity:1,height:"auto"},exit:{opacity:0,height:0},children:N?t.jsx(Ye,{password:c,requirements:N}):t.jsxs(t.Fragment,{children:[t.jsx(Fe,{theme:a,children:"Password Requirements:"}),t.jsx(Me,{theme:a,children:x.requirements.map(s=>t.jsxs(Ae,{theme:a,children:[t.jsx(_e,{theme:a,met:s.met,children:s.met?t.jsx(Te,{theme:a,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:t.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})}):t.jsx(Oe,{theme:a})}),t.jsx(Ee,{theme:a,met:s.met,children:s.label})]},s.id))})]})})}),t.jsx(w.AnimatePresence,{children:pe&&x&&t.jsx(Ve,{theme:a,children:H.length>0&&t.jsxs(t.Fragment,{children:[t.jsx(We,{theme:a,children:"Suggested passwords:"}),t.jsx(Be,{theme:a,children:H.map((s,be)=>t.jsx(Ne,{theme:a,type:"button",children:s},be))})]})})}),t.jsx(w.AnimatePresence,{children:re&&t.jsx(z.Button,{type:"button",variant:"light",size:"sm",onPress:ye,children:"Generate secure password"})})]})}const M=u.default.memo(te);function Qe({originalPassword:e,...r}){return t.jsx(M,{...r,name:r.name||"passwordConfirmation",label:r.label||"Confirm Password",placeholder:r.placeholder||"Confirm your password",autoComplete:"new-password",isConfirmation:!0,originalPassword:e,showStrength:!1,showRequirements:!1})}function Ye({password:e,requirements:r}){const{theme:d}=F.useTheme(),c=K.getPasswordStrength(e),o=l=>{switch(l){case"weak":return"danger";case"fair":return"warning";case"good":return"primary";case"strong":return"success";default:return"default"}},h=l=>{switch(l){case"weak":return"Weak";case"fair":return"Fair";case"good":return"Good";case"strong":return"Strong";default:return""}};return e?t.jsxs(Y,{theme:d,children:[t.jsxs(ee,{theme:d,children:[t.jsx(J.Progress,{value:c.score/6*100,color:o(c.strength),size:"xs",style:{flex:1}}),t.jsx($e.Chip,{size:"sm",color:o(c.strength),variant:"flat",children:h(c.strength)})]}),c.feedback.length>0&&t.jsx(Ue,{theme:d,children:c.feedback.map((l,m)=>t.jsxs(Ge,{theme:d,children:[t.jsx(Ze,{theme:d,as:q.ExclamationTriangleIcon}),t.jsx("span",{children:l})]},m))}),r&&t.jsxs(De,{theme:d,children:[r.minLength&&t.jsx(j,{met:e.length>=r.minLength,text:`At least ${r.minLength} characters`}),r.requireUppercase&&t.jsx(j,{met:/[A-Z]/.test(e),text:"One uppercase letter"}),r.requireLowercase&&t.jsx(j,{met:/[a-z]/.test(e),text:"One lowercase letter"}),r.requireNumbers&&t.jsx(j,{met:/\d/.test(e),text:"One number"}),r.requireSymbols&&t.jsx(j,{met:/[!@#$%^&*(),.?":{}|<>]/.test(e),text:"One symbol"})]})]}):null}function j({met:e,text:r}){const{theme:d}=F.useTheme();return t.jsxs(He,{theme:d,met:e,children:[t.jsx(Xe,{theme:d,met:e,as:q.CheckIcon}),t.jsx("span",{children:r})]})}var et=M;exports.PasswordConfirmationField=Qe;exports.PasswordField=M;exports.PasswordFieldComponent=te;exports.StyledSvg=R;exports.default=et;
//# sourceMappingURL=password-field.cjs.map