import * as React from "react"; import { Check, X } from "lucide-react"; import { Popover as PopoverPrimitive } from "@base-ui/react/popover"; import { cn } from "@/lib/utils"; import { useThemeVars } from "@/lib/theme-provider"; export type PasswordStrengthRule = { label: string; test: (p: string) => boolean; }; export const PASSWORD_STRENGTH_RULES: PasswordStrengthRule[] = [ { label: "Minimum 8 characters", test: (p) => p.length >= 8 }, { label: "At least one uppercase letter", test: (p) => /[A-Z]/.test(p) }, { label: "At least one lowercase letter", test: (p) => /[a-z]/.test(p) }, { label: "At least one number", test: (p) => /\d/.test(p) }, { label: "At least one special character", test: (p) => /[^A-Za-z0-9]/.test(p), }, ]; export type PasswordStrengthTooltipProps = { open?: boolean; password: string; children: React.ReactNode; side?: "top" | "right" | "bottom" | "left"; onRequestClose?: () => void; }; export const PasswordStrengthTooltip = React.forwardRef< HTMLDivElement, PasswordStrengthTooltipProps >(function PasswordStrengthTooltip( { open = false, password, children, side = "right" }, forwardedRef ) { const themeVars = useThemeVars(); // anchorRef is used by Positioner for popup placement. // forwardedRef (fieldRef from consumer) is used for contains() checks in dismiss logic. const anchorRef = React.useRef(null); const composedRef = React.useCallback( (node: HTMLDivElement | null) => { (anchorRef as React.MutableRefObject).current = node; if (typeof forwardedRef === "function") { forwardedRef(node); } else if (forwardedRef) { ( forwardedRef as React.MutableRefObject ).current = node; } }, // eslint-disable-next-line react-hooks/exhaustive-deps [forwardedRef] ); return ( // PopoverPrimitive.Root with no Trigger — popup is fully controlled via `open` prop. // The wrapper div has no trigger behaviors injected, so clicking the input inside // works on the first click without interference.
{children}
{PASSWORD_STRENGTH_RULES.map((rule) => { const valid = password ? rule.test(password) : false; return (
{valid ? ( ) : ( )} {rule.label}
); })}
); });