mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 04:42:03 +00:00
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
|
|
import { Circle, CircleCheck } from "lucide-react";
|
||
|
|
|
||
|
|
import { Text } from "@/components/ui/text";
|
||
|
|
import { evaluatePasswordRules } from "@/domain/auth/password-policy";
|
||
|
|
import { cn } from "@/lib/utils";
|
||
|
|
|
||
|
|
export type PasswordChecklistProps = {
|
||
|
|
password: string;
|
||
|
|
id?: string;
|
||
|
|
className?: string;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Live, per-rule feedback for the shared password policy. */
|
||
|
|
export function PasswordChecklist({ password, id, className }: PasswordChecklistProps) {
|
||
|
|
const results = evaluatePasswordRules(password);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<ul
|
||
|
|
id={id}
|
||
|
|
aria-label="Password requirements"
|
||
|
|
className={cn("m-0 mt-2 grid list-none gap-1 p-0", className)}
|
||
|
|
>
|
||
|
|
{results.map(({ id: ruleId, label, met }) => (
|
||
|
|
<li key={ruleId} data-rule={ruleId} data-met={met} className="flex items-center gap-1.5">
|
||
|
|
{met ? (
|
||
|
|
<CircleCheck size={13} aria-hidden="true" className="text-(--color-success)" />
|
||
|
|
) : (
|
||
|
|
<Circle size={13} aria-hidden="true" className="text-(--color-text-muted)" />
|
||
|
|
)}
|
||
|
|
<Text variant="caption" tone={met ? "success" : "muted"}>
|
||
|
|
{label}
|
||
|
|
</Text>
|
||
|
|
<span className="sr-only">{met ? "requirement met" : "requirement not met"}</span>
|
||
|
|
</li>
|
||
|
|
))}
|
||
|
|
</ul>
|
||
|
|
);
|
||
|
|
}
|