PasswordConditionsHelper.tsx72 lines · main
| 1 | export type PasswordConditionsHelperProps = { |
| 2 | password: string |
| 3 | } |
| 4 | |
| 5 | const PasswordConditionsHelper = ({ password }: PasswordConditionsHelperProps) => { |
| 6 | const isEightCharactersLong = password.length >= 8 |
| 7 | const hasUppercase = /[A-Z]/.test(password) |
| 8 | const hasLowercase = /[a-z]/.test(password) |
| 9 | const hasNumber = /[0-9]/.test(password) |
| 10 | const hasSpecialCharacter = /[!@#$%^&*()_+\-=\[\]{};`':"\\|,.<>\/?]/.test(password) |
| 11 | |
| 12 | return ( |
| 13 | <div className="text-sm"> |
| 14 | <PasswordCondition title="Uppercase letter" isMet={hasUppercase} /> |
| 15 | <PasswordCondition title="Lowercase letter" isMet={hasLowercase} /> |
| 16 | <PasswordCondition title="Number" isMet={hasNumber} /> |
| 17 | <PasswordCondition title="Special character (e.g. !?<>@#$%)" isMet={hasSpecialCharacter} /> |
| 18 | <PasswordCondition title="8 characters or more" isMet={isEightCharactersLong} /> |
| 19 | {password.length > 72 && <PasswordCondition title="72 characters or less" isMet={false} />} |
| 20 | </div> |
| 21 | ) |
| 22 | } |
| 23 | |
| 24 | export default PasswordConditionsHelper |
| 25 | |
| 26 | type PasswordConditionProps = { |
| 27 | title: string |
| 28 | isMet: boolean |
| 29 | } |
| 30 | |
| 31 | const PasswordCondition = ({ title, isMet }: PasswordConditionProps) => { |
| 32 | return ( |
| 33 | <div |
| 34 | className={ |
| 35 | 'flex items-center gap-1 space-x-1.5 transition duration-200 ' + |
| 36 | (isMet ? 'text-foreground-light' : 'text-foreground-lighter') |
| 37 | } |
| 38 | > |
| 39 | {isMet ? ( |
| 40 | <svg |
| 41 | xmlns="http://www.w3.org/2000/svg" |
| 42 | viewBox="0 0 24 24" |
| 43 | fill="currentColor" |
| 44 | className="w-4 h-4" |
| 45 | > |
| 46 | <path |
| 47 | fillRule="evenodd" |
| 48 | d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zm13.36-1.814a.75.75 0 10-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.14-.094l3.75-5.25z" |
| 49 | clipRule="evenodd" |
| 50 | /> |
| 51 | </svg> |
| 52 | ) : ( |
| 53 | <svg |
| 54 | xmlns="http://www.w3.org/2000/svg" |
| 55 | fill="none" |
| 56 | stroke="currentColor" |
| 57 | strokeWidth={1.5} |
| 58 | viewBox="0 0 24 24" |
| 59 | className="w-4 h-4" |
| 60 | > |
| 61 | <path |
| 62 | strokeLinecap="round" |
| 63 | strokeLinejoin="round" |
| 64 | d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z" |
| 65 | /> |
| 66 | </svg> |
| 67 | )} |
| 68 | |
| 69 | <p className="text-sm">{title}</p> |
| 70 | </div> |
| 71 | ) |
| 72 | } |