"use client"; import * as React from "react"; import { cn } from "./lib/utils"; export interface PasswordStrengthProps extends React.HTMLAttributes { value?: string; className?: string; showCriteria?: boolean; } interface Criteria { label: string; met: boolean; } export function PasswordStrength({ value = "", className, showCriteria = true, ...props }: PasswordStrengthProps) { const criteria: Criteria[] = React.useMemo(() => [ { label: "MIN 8 CHARACTERS", met: value.length >= 8 }, { label: "UPPERCASE & LOWERCASE", met: /[A-Z]/.test(value) && /[a-z]/.test(value) }, { label: "NUMERIC DIGIT (0-9)", met: /[0-9]/.test(value) }, { label: "SPECIAL SYMBOL (#$@!)", met: /[^A-Za-z0-9]/.test(value) }, ], [value]); const metCount = criteria.filter((c) => c.met).length; const strengthLevel = React.useMemo(() => { if (value.length === 0) return { label: "NO TICKET KEY", color: "bg-muted", width: "0%" }; if (metCount <= 1) return { label: "REVOKED / WEAK", color: "bg-destructive", width: "25%" }; if (metCount === 2) return { label: "STANDBY / FAIR", color: "bg-warning", width: "50%" }; if (metCount === 3) return { label: "VALID / GOOD", color: "bg-warning", width: "75%" }; return { label: "SECURE / ADMITTED", color: "bg-success", width: "100%" }; }, [value, metCount]); return (
{/* Header Info */}
SECURITY METER {strengthLevel.label}
{/* Segmented Meter Bar */}
{[0, 1, 2, 3].map((step) => { const isActive = step < metCount; return (
); })}
{/* Criteria Checklist */} {showCriteria && (
{criteria.map((c, i) => (
✓ {c.label}
))}
)}
); }