/** * Copyright (c) 2023-present Plane Software, Inc. and contributors * SPDX-License-Identifier: AGPL-3.0-only * See the LICENSE file for details. */ import { TickCircleOutline } from "@makeplane/propel/icons"; // plane internal packages import { E_PASSWORD_STRENGTH } from "@plane/constants"; import { cn, getPasswordCriteria, getPasswordStrength } from "@plane/utils"; interface StrengthInfo { message: string; textColor: string; activeFragments: number; } /** * Get strength information including message, color, and active fragments */ const getStrengthInfo = (strength: E_PASSWORD_STRENGTH): StrengthInfo => { switch (strength) { case E_PASSWORD_STRENGTH.EMPTY: return { message: "Please enter your password", textColor: "text-primary", activeFragments: 0, }; case E_PASSWORD_STRENGTH.LENGTH_NOT_VALID: return { message: "Password is too short", textColor: "text-danger-primary", activeFragments: 1, }; case E_PASSWORD_STRENGTH.STRENGTH_NOT_VALID: return { message: "Password is weak", textColor: "text-orange-500", activeFragments: 2, }; case E_PASSWORD_STRENGTH.STRENGTH_VALID: return { message: "Password is strong", textColor: "text-success-primary", activeFragments: 3, }; default: return { message: "Please enter your password", textColor: "text-primary", activeFragments: 0, }; } }; /** * Get fragment color based on position and active state */ const getFragmentColor = (fragmentIndex: number, activeFragments: number): string => { if (fragmentIndex >= activeFragments) { return "bg-layer-1"; } switch (activeFragments) { case 1: return "bg-danger-primary"; case 2: return "bg-orange-500"; case 3: return "bg-success-primary"; default: return "bg-layer-1"; } }; export interface PasswordStrengthIndicatorProps { password: string; showCriteria?: boolean; isFocused?: boolean; } export function PasswordStrengthIndicator({ password, showCriteria = true, isFocused = false, }: PasswordStrengthIndicatorProps) { const strength = getPasswordStrength(password); const criteria = getPasswordCriteria(password); const strengthInfo = getStrengthInfo(strength); const isPasswordMeterVisible = isFocused ? true : strength === E_PASSWORD_STRENGTH.STRENGTH_VALID ? false : true; if ((!password && !showCriteria) || !isPasswordMeterVisible) { return null; } return (
{/* Strength Indicator */}
{[0, 1, 2].map((fragmentIndex) => (
))}
{/* Strength Message */} {password &&

{strengthInfo.message}

}
{/* Criteria list */} {showCriteria && (
{criteria.map((criterion) => (
{criterion.label}
))}
)}
); }