"use client"; import { cn } from "@/lib/utils"; import { PASSWORD_MIN } from "./auth-errors"; const COMMON = ["password", "qwerty", "letmein", "welcome", "iloveyou", "admin", "monkey", "dragon", "polyllm", "abc123", "123456"]; /** Client-side heuristic (0–4). Not a substitute for server-side policy; it only guides the user. */ export function scorePassword(pw: string): { score: 0 | 1 | 2 | 3 | 4; label: string; hint: string } { if (!pw) return { score: 0, label: "", hint: `At least ${PASSWORD_MIN} characters. Long and memorable beats short and clever.` }; if (pw.length < PASSWORD_MIN) return { score: 0, label: "Too short", hint: `${PASSWORD_MIN - pw.length} more character${PASSWORD_MIN - pw.length === 1 ? "" : "s"} to go.` }; let points = 0; const lower = /[a-z]/.test(pw); const upper = /[A-Z]/.test(pw); const digit = /\d/.test(pw); const symbol = /[^A-Za-z0-9]/.test(pw); const variety = [lower, upper, digit, symbol].filter(Boolean).length; points += pw.length >= 14 ? 2 : 1; points += pw.length >= 20 ? 1 : 0; points += variety >= 3 ? 1 : 0; points += variety === 4 ? 1 : 0; const lowered = pw.toLowerCase(); if (COMMON.some((c) => lowered.includes(c))) points -= 2; if (/(.)\1{2,}/.test(pw)) points -= 1; // aaa if (/(0123|1234|2345|3456|4567|5678|6789|abcd|qwer|asdf)/i.test(pw)) points -= 1; if (new Set(pw).size <= Math.max(3, pw.length / 4)) points -= 1; // very low entropy const score = Math.max(1, Math.min(4, points)) as 1 | 2 | 3 | 4; const labels: Record<1 | 2 | 3 | 4, [string, string]> = { 1: ["Weak", "Add length or mix in words, numbers and symbols."], 2: ["Fair", "A few more characters would make this much stronger."], 3: ["Good", "Solid. Longer is always better."], 4: ["Strong", "Excellent. Store it in a password manager."], }; return { score, label: labels[score][0], hint: labels[score][1] }; } const COLORS = ["bg-border-strong", "bg-danger", "bg-warning", "bg-info", "bg-success"]; const TEXT = ["text-fg-subtle", "text-danger", "text-warning", "text-info", "text-success"]; export function PasswordStrength({ password, id }: { password: string; id?: string }) { const { score, label, hint } = scorePassword(password); return (
{[1, 2, 3, 4].map((i) => ( ))}

{hint} {label ? {label} : null}

); }