Presupuestador_web/client/src/components/Forms/FormTextField.tsx

117 lines
3.2 KiB
TypeScript
Raw Normal View History

2024-06-06 11:05:54 +00:00
import { cn } from "@/lib/utils";
import {
FormControl,
FormDescription,
FormField,
FormItem,
FormMessage,
Input,
InputProps,
} from "@/ui";
import * as React from "react";
import { createElement } from "react";
2024-06-29 19:39:25 +00:00
import {
FieldErrors,
FieldPath,
FieldValues,
UseControllerProps,
useFormContext,
} from "react-hook-form";
2024-06-06 11:05:54 +00:00
import { FormLabel, FormLabelProps } from "./FormLabel";
import { FormInputProps, FormInputWithIconProps } from "./FormProps";
export type FormTextFieldProps<
TFieldValues extends FieldValues = FieldValues,
2024-06-17 10:42:44 +00:00
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
2024-06-06 11:05:54 +00:00
> = {
2024-06-17 10:42:44 +00:00
button?: (props?: React.PropsWithChildren) => React.ReactNode;
2024-06-06 11:05:54 +00:00
} & InputProps &
FormInputProps &
Partial<FormLabelProps> &
FormInputWithIconProps &
UseControllerProps<TFieldValues, TName> & {
errors?: FieldErrors<TFieldValues>;
};
2024-06-17 10:42:44 +00:00
export const FormTextField = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & FormTextFieldProps
>((props, ref) => {
const {
label,
placeholder,
hint,
description,
required,
className,
leadIcon,
trailIcon,
button,
disabled,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
errors,
name,
type,
} = props;
2024-06-06 11:05:54 +00:00
2024-06-29 19:39:25 +00:00
const { control } = useFormContext();
2024-06-06 11:05:54 +00:00
return (
<FormField
control={control}
name={name}
rules={{ required }}
disabled={disabled}
2024-06-17 10:42:44 +00:00
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2024-06-06 11:05:54 +00:00
render={({ field, fieldState, formState }) => (
2024-06-17 10:42:44 +00:00
<FormItem ref={ref} className={cn(className, "space-y-3")}>
2024-06-29 19:39:25 +00:00
{label && <FormLabel label={label} hint={hint} required={required} />}
2024-06-06 11:05:54 +00:00
<div className={cn(button ? "flex" : null)}>
<div
className={cn(
2024-06-17 10:42:44 +00:00
leadIcon ? "relative flex items-stretch flex-grow focus-within:z-10" : ""
2024-06-06 11:05:54 +00:00
)}
>
{leadIcon && (
2024-06-17 10:42:44 +00:00
<div className='absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none'>
2024-06-06 11:05:54 +00:00
{React.createElement(
leadIcon,
{
className: "h-5 w-5 text-muted-foreground",
"aria-hidden": true,
},
2024-06-17 10:42:44 +00:00
null
2024-06-06 11:05:54 +00:00
)}
</div>
)}
<FormControl
2024-06-17 10:42:44 +00:00
className={cn("block", leadIcon ? "pl-10" : "", trailIcon ? "pr-10" : "")}
2024-06-06 11:05:54 +00:00
>
2024-06-17 10:42:44 +00:00
<Input type={type} placeholder={placeholder} disabled={disabled} {...field} />
2024-06-06 11:05:54 +00:00
</FormControl>
{trailIcon && (
2024-06-17 10:42:44 +00:00
<div className='absolute inset-y-0 right-0 flex items-center pl-3 pointer-events-none'>
2024-06-06 11:05:54 +00:00
{createElement(
trailIcon,
{
className: "h-5 w-5 text-muted-foreground",
"aria-hidden": true,
},
2024-06-17 10:42:44 +00:00
null
2024-06-06 11:05:54 +00:00
)}
</div>
)}
</div>
{button && <>{createElement(button)}</>}
</div>
{description && <FormDescription>{description}</FormDescription>}
<FormMessage />
</FormItem>
)}
/>
);
2024-06-17 10:42:44 +00:00
});