121 lines
3.1 KiB
TypeScript
121 lines
3.1 KiB
TypeScript
|
|
import { cn } from "@/lib/utils";
|
||
|
|
import {
|
||
|
|
FormControl,
|
||
|
|
FormDescription,
|
||
|
|
FormField,
|
||
|
|
FormItem,
|
||
|
|
FormMessage,
|
||
|
|
Input,
|
||
|
|
InputProps,
|
||
|
|
} from "@/ui";
|
||
|
|
|
||
|
|
import * as React from "react";
|
||
|
|
import { createElement } from "react";
|
||
|
|
import {
|
||
|
|
FieldErrors,
|
||
|
|
FieldPath,
|
||
|
|
FieldValues,
|
||
|
|
UseControllerProps,
|
||
|
|
} from "react-hook-form";
|
||
|
|
import { FormLabel, FormLabelProps } from "./FormLabel";
|
||
|
|
import { FormInputProps, FormInputWithIconProps } from "./FormProps";
|
||
|
|
|
||
|
|
export type FormTextFieldProps<
|
||
|
|
TFieldValues extends FieldValues = FieldValues,
|
||
|
|
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||
|
|
> = {
|
||
|
|
button?: (props?) => React.ReactNode;
|
||
|
|
} & InputProps &
|
||
|
|
FormInputProps &
|
||
|
|
Partial<FormLabelProps> &
|
||
|
|
FormInputWithIconProps &
|
||
|
|
UseControllerProps<TFieldValues, TName> & {
|
||
|
|
errors?: FieldErrors<TFieldValues>;
|
||
|
|
};
|
||
|
|
|
||
|
|
export function FormTextField({
|
||
|
|
label,
|
||
|
|
placeholder,
|
||
|
|
hint,
|
||
|
|
description,
|
||
|
|
required,
|
||
|
|
className,
|
||
|
|
leadIcon,
|
||
|
|
trailIcon,
|
||
|
|
button,
|
||
|
|
disabled,
|
||
|
|
errors,
|
||
|
|
name,
|
||
|
|
control,
|
||
|
|
type,
|
||
|
|
}: FormTextFieldProps) {
|
||
|
|
//const error = Boolean(errors && errors[name]);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<FormField
|
||
|
|
control={control}
|
||
|
|
name={name}
|
||
|
|
rules={{ required }}
|
||
|
|
disabled={disabled}
|
||
|
|
render={({ field, fieldState, formState }) => (
|
||
|
|
<FormItem className={cn(className, "space-y-3")}>
|
||
|
|
{label && <FormLabel label={label} hint={hint} />}
|
||
|
|
<div className={cn(button ? "flex" : null)}>
|
||
|
|
<div
|
||
|
|
className={cn(
|
||
|
|
leadIcon
|
||
|
|
? "relative flex items-stretch flex-grow focus-within:z-10"
|
||
|
|
: "",
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
{leadIcon && (
|
||
|
|
<div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
||
|
|
{React.createElement(
|
||
|
|
leadIcon,
|
||
|
|
{
|
||
|
|
className: "h-5 w-5 text-muted-foreground",
|
||
|
|
"aria-hidden": true,
|
||
|
|
},
|
||
|
|
null,
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
<FormControl
|
||
|
|
className={cn(
|
||
|
|
"block",
|
||
|
|
leadIcon ? "pl-10" : "",
|
||
|
|
trailIcon ? "pr-10" : "",
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
<Input
|
||
|
|
type={type}
|
||
|
|
placeholder={placeholder}
|
||
|
|
disabled={disabled}
|
||
|
|
{...field}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
|
||
|
|
{trailIcon && (
|
||
|
|
<div className="absolute inset-y-0 right-0 flex items-center pl-3 pointer-events-none">
|
||
|
|
{createElement(
|
||
|
|
trailIcon,
|
||
|
|
{
|
||
|
|
className: "h-5 w-5 text-muted-foreground",
|
||
|
|
"aria-hidden": true,
|
||
|
|
},
|
||
|
|
null,
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
{button && <>{createElement(button)}</>}
|
||
|
|
</div>
|
||
|
|
{description && <FormDescription>{description}</FormDescription>}
|
||
|
|
<FormMessage />
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
}
|