/* * Copyright (c) 2021 - 2025, Ludvig Lundgren and the autobrr contributors. * SPDX-License-Identifier: GPL-2.0-or-later */ import { FC, forwardRef, ReactNode } from "react"; import { DeepMap, FieldError, Path, RegisterOptions, UseFormRegister } from "react-hook-form"; import { classNames, get } from "@utils"; import { useToggle } from "@hooks/hooks"; import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/solid"; import { ErrorMessage } from "@hookform/error-message"; import type { FieldValues } from "react-hook-form"; export type FormErrorMessageProps = { className?: string; children: ReactNode; }; export const FormErrorMessage: FC = ({ children, className }) => (

{children}

); export type InputType = "text" | "email" | "password"; export type InputAutoComplete = "username" | "current-password"; export type InputColumnWidth = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; export type InputProps = { id: string; name: string; label: string; type?: InputType; className?: string; placeholder?: string; autoComplete?: InputAutoComplete; isHidden?: boolean; columnWidth?: InputColumnWidth; }; // Using maps so that the full Tailwind classes can be seen for purging // see https://tailwindcss.com/docs/optimizing-for-production#writing-purgeable-html // const sizeMap: { [key in InputSize]: string } = { // medium: "p-3 text-base", // large: "p-4 text-base" // }; export const Input: FC = forwardRef( ( { id, name, label, type , className = "", placeholder, autoComplete, ...props }, ref ) => { return ( ); } ); export type FormInputProps = { name: Path; rules?: RegisterOptions>; register?: UseFormRegister; errors?: Partial>; } & Omit; export const TextInput = >({ name, register, rules, errors, isHidden, columnWidth, ...props }: FormInputProps): JSX.Element => { // If the name is in a FieldArray, it will be 'fields.index.fieldName' and errors[name] won't return anything, so we are using lodash get const errorMessages = get(errors, name); const hasError = !!(errors && errorMessages); return (
{props.label && ( )}
( {message} )} />
); }; export const PasswordInput = >({ name, register, rules, errors, isHidden, columnWidth, ...props }: FormInputProps): JSX.Element => { const [isVisible, toggleVisibility] = useToggle(false); // If the name is in a FieldArray, it will be 'fields.index.fieldName' and errors[name] won't return anything, so we are using lodash get const errorMessages = get(errors, name); const hasError = !!(errors && errorMessages); return (
{props.label && ( )}
{!isVisible ?
( {message} )} />
); };