From 7df42ddf5827b1eb2427739c071733029c1e451e Mon Sep 17 00:00:00 2001 From: Cryptoryda <113293883+cryptoryda@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:26:32 +0000 Subject: [PATCH] password toolkit ui matches with main three lines --- .../InputSecurePassword.tsx | 200 +++++++++++++----- 1 file changed, 146 insertions(+), 54 deletions(-) diff --git a/packages/app/src/systems/Core/components/InputSecurePassword/InputSecurePassword.tsx b/packages/app/src/systems/Core/components/InputSecurePassword/InputSecurePassword.tsx index afd5ac874d..185cbe2677 100644 --- a/packages/app/src/systems/Core/components/InputSecurePassword/InputSecurePassword.tsx +++ b/packages/app/src/systems/Core/components/InputSecurePassword/InputSecurePassword.tsx @@ -1,16 +1,10 @@ -import type { ThemeUtilsCSS } from '@fuel-ui/css'; -import { cssObj } from '@fuel-ui/css'; -import type { InputPasswordProps } from '@fuel-ui/react'; -import { - Box, - Icon, - InputPassword, - PasswordStrength, - usePasswordStrength, -} from '@fuel-ui/react'; -import unsafeList from '@fuel-ui/react/unsafe-passwords'; -import { useEffect, useState } from 'react'; -import type { ControllerRenderProps, FieldValues } from 'react-hook-form'; +import type { ThemeUtilsCSS } from "@fuel-ui/css"; +import { cssObj } from "@fuel-ui/css"; +import type { InputPasswordProps } from "@fuel-ui/react"; +import { Box, Icon, InputPassword } from "@fuel-ui/react"; +import { useEffect, useState } from "react"; +import React from "react"; +import type { ControllerRenderProps, FieldValues } from "react-hook-form"; export type InputSecurePasswordProps = { onChangeStrength?: (strength: string) => void; @@ -25,51 +19,128 @@ export type InputSecurePasswordProps = { css?: ThemeUtilsCSS; }; +const calculatePasswordStrength = (password: string): string => { + let score = 0; + + if (password.length >= 8) score += 1; + if (/[a-z]/.test(password) && /[A-Z]/.test(password)) score += 1; + if (/\d/.test(password)) score += 1; + if (/[@$!%*?&#^_-]/.test(password)) score += 1; + + if (score <= 1) return "weak"; + if (score === 2) return "average"; + if (score >= 3) return "strong"; + + return "weak"; +}; + export function InputSecurePassword({ inputProps, field, onChangeStrength, onChange, onBlur, - placeholder = 'Type your password', - ariaLabel = 'Your Password', + placeholder = "Type your password", + ariaLabel = "Your Password", css, }: InputSecurePasswordProps) { const [passwordTooltipOpened, setPasswordTooltipOpened] = useState(false); - const password = field.value || ''; - const { strength } = usePasswordStrength({ - minLength: 8, - password, - unsafeList, - }); + const [strength, setStrength] = useState("weak"); + const password = field.value || ""; - // biome-ignore lint/correctness/useExhaustiveDependencies: useEffect(() => { - onChangeStrength?.(strength); - }, [strength]); + const currentStrength = calculatePasswordStrength(password); + setStrength(currentStrength); + onChangeStrength?.(currentStrength); + }, [password, onChangeStrength]); + + const getStrengthColor = (level: string, index: number) => { + if (level === "weak") { + return index === 0 ? "red" : "gray"; + } + if (level === "average") { + return index === 0 || index === 1 ? "yellow" : "gray"; + } + if (level === "strong") { + return "green"; + } + return "gray"; // Default to gray for any unexpected case + }; return ( - - + {[...Array(3)].map((_, index) => ( + + ))} + + + {/* Tooltip Wrapper */} + setPasswordTooltipOpened(true)} onMouseLeave={() => setPasswordTooltipOpened(false)} - aria-label="Password strength" > - - - - + + {passwordTooltipOpened && ( + + + + {strength.charAt(0).toUpperCase() + strength.slice(1)} + + + + {[...Array(3)].map((_, index) => ( + + ))} + + + +

A secure password should have:

+
    +
  • {password.length >= 8 ? "✓" : "✗"} Min. 8 characters
  • +
  • + {/[a-z]/.test(password) && /[A-Z]/.test(password) + ? "✓" + : "✗"}{" "} + Upper & lower case letters +
  • +
  • {/\d/.test(password) ? "✓" : "✗"} Numbers
  • +
  • + {/[@$!%*?&#^_-]/.test(password) ? "✓" : "✗"} Special + characters +
  • +
+
+
+ )} +
+ +