"use client";
/**
* Password field with show/hide eye control.
* Use this for every password input in the portal.
*/
import { useState, type ReactNode } from "react";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";
export function PasswordInput({
id,
label,
value,
onChange,
placeholder,
autoComplete = "current-password",
disabled,
className,
inputClassName,
onEnter,
hideLabel,
}: {
id: string;
/** Visible label; use empty + hideLabel for icon-only contexts */
label?: string;
value: string;
onChange: (value: string) => void;
placeholder?: string;
autoComplete?: string;
disabled?: boolean;
className?: string;
inputClassName?: string;
onEnter?: () => void;
hideLabel?: boolean;
}) {
const [show, setShow] = useState(false);
const accessibleName = label || placeholder || "Password";
return (
{label && !hideLabel ? (
{label}
) : (
{accessibleName}
)}
onChange(e.target.value)}
placeholder={placeholder}
className={cn("pr-11", inputClassName)}
onKeyDown={(e) => {
if (e.key === "Enter") onEnter?.();
}}
/>
setShow((v) => !v)}
className="absolute inset-y-0 right-0 flex min-w-11 items-center justify-center rounded-r-md text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-inset disabled:pointer-events-none disabled:opacity-50"
aria-label={show ? `Hide ${accessibleName}` : `Show ${accessibleName}`}
aria-pressed={show}
title={show ? "Hide password" : "Show password"}
>
{show ? : }
);
}
/** Alias used by mavi screens */
export function PasswordField(
props: Parameters[0],
): ReactNode {
return ;
}
function EyeIcon() {
return (
);
}
function EyeOffIcon() {
return (
);
}