53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
import { useState } from "react";
|
|
import { useFieldContext } from "..";
|
|
import { FieldErrors } from "./FieldErrors";
|
|
import { Eye, EyeOff } from "lucide-react";
|
|
import { Label } from "../../../components/ui/label";
|
|
import { Input } from "../../../components/ui/input";
|
|
import { Button } from "../../../components/ui/button";
|
|
|
|
type PasswordInputProps = {
|
|
label: string;
|
|
required?: boolean;
|
|
};
|
|
|
|
export const InputPasswordField = ({
|
|
label,
|
|
required = false,
|
|
}: PasswordInputProps) => {
|
|
const field = useFieldContext<any>();
|
|
const [show, setShow] = useState(false);
|
|
|
|
return (
|
|
<div className="grid gap-3">
|
|
<Label htmlFor={field.name}>{label}</Label>
|
|
<div className="relative">
|
|
<Input
|
|
id={field.name}
|
|
type={show ? "text" : "password"}
|
|
value={field.state.value}
|
|
onChange={(e) => field.handleChange(e.target.value)}
|
|
onBlur={field.handleBlur}
|
|
required={required}
|
|
className="pr-10"
|
|
/>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={() => setShow((p) => !p)}
|
|
className="absolute right-1 top-1/2 -translate-y-1/2 h-7 w-7"
|
|
tabIndex={-1} // prevent messing with tab order
|
|
>
|
|
{show ? (
|
|
<EyeOff className="h-4 w-4" />
|
|
) : (
|
|
<Eye className="h-4 w-4" />
|
|
)}
|
|
</Button>
|
|
</div>
|
|
<FieldErrors meta={field.state.meta} />
|
|
</div>
|
|
);
|
|
};
|