78 lines
2.1 KiB
TypeScript

import { forwardRef, useId } from "react";
import { Controller, FieldValues, Path } from "react-hook-form";
import { useFormReturn } from "~/hooks/useForm";
import { cn } from "~/lib/utils";
import FormField, { FormFieldProps } from "./form-field";
export type BaseInputProps = React.InputHTMLAttributes<HTMLInputElement> &
FormFieldProps & {
inputClassName?: string;
};
const BaseInput = forwardRef<HTMLInputElement, BaseInputProps>(
({ className, inputClassName, type, label, error, ...props }, ref) => {
const id = useId();
const input = (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-slate-200 px-3 py-2 text-sm ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/40 bg-transparent dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300",
label || error ? inputClassName : className
)}
ref={ref}
{...props}
/>
);
if (label || error) {
return (
<FormField
id={id}
label={label}
error={error}
className={className}
children={input}
/>
);
}
return input;
}
);
BaseInput.displayName = "BaseInput";
type InputProps<T extends FieldValues> = Omit<
BaseInputProps,
"form" | "name"
> & {
form?: useFormReturn<T>;
name?: Path<T>;
};
const Input = <T extends FieldValues>(props: InputProps<T>) => {
const { form, ...restProps } = props;
if (form && props.name) {
return (
<Controller
control={form.control}
name={props.name}
render={({ field, fieldState }) => (
<BaseInput
{...restProps}
{...field}
value={field.value || ""}
error={fieldState.error?.message}
/>
)}
/>
);
}
return <BaseInput {...restProps} />;
};
export { BaseInput };
export default Input;