|
1 | | -import type * as React from 'react'; |
| 1 | +import * as React from 'react'; |
2 | 2 | import type { Control, FieldPath, FieldValues } from 'react-hook-form'; |
3 | 3 | import { |
4 | 4 | type FieldComponents, |
@@ -57,64 +57,57 @@ export interface TextInputProps extends Omit<InputProps, 'prefix' | 'suffix'> { |
57 | 57 | label?: string; |
58 | 58 | description?: string; |
59 | 59 | components?: Partial<FieldComponents> & { |
60 | | - Input?: React.ComponentType<InputProps>; |
| 60 | + Input?: React.ComponentType<InputProps & React.RefAttributes<HTMLInputElement>>; |
61 | 61 | }; |
62 | 62 | prefix?: React.ReactNode; |
63 | 63 | suffix?: React.ReactNode; |
64 | 64 | className?: string; |
65 | 65 | } |
66 | 66 |
|
67 | | -export const TextField = ({ |
68 | | - control, |
69 | | - name, |
70 | | - label, |
71 | | - description, |
72 | | - className, |
73 | | - components, |
74 | | - prefix, |
75 | | - suffix, |
76 | | - ...props |
77 | | -}: TextInputProps) => { |
78 | | - // Use the custom Input component if provided, otherwise use the default TextInput |
79 | | - const InputComponent = components?.Input || TextInput; |
| 67 | +export const TextField = React.forwardRef<HTMLInputElement, TextInputProps>( |
| 68 | + ({ control, name, label, description, className, components, prefix, suffix, ...props }, ref) => { |
| 69 | + // Use the custom Input component if provided, otherwise use the default TextInput |
| 70 | + const InputComponent = components?.Input || TextInput; |
80 | 71 |
|
81 | | - return ( |
82 | | - <FormField |
83 | | - control={control} |
84 | | - name={name} |
85 | | - render={({ field, fieldState }) => { |
86 | | - return ( |
87 | | - <FormItem className={className}> |
88 | | - {label && <FormLabel Component={components?.FormLabel}>{label}</FormLabel>} |
89 | | - <div |
90 | | - className={cn('flex group transition-all duration-200 rounded-md', { |
91 | | - 'field__input--with-prefix': prefix, |
92 | | - 'field__input--with-suffix': suffix, |
93 | | - 'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background': true, |
94 | | - })} |
95 | | - > |
96 | | - {prefix && <FieldPrefix>{prefix}</FieldPrefix>} |
97 | | - <FormControl Component={components?.FormControl}> |
98 | | - <InputComponent |
99 | | - {...field} |
100 | | - {...props} |
101 | | - className={cn('focus-visible:ring-0 focus-visible:ring-offset-0 border-input', { |
102 | | - 'rounded-l-none border-l-0': prefix, |
103 | | - 'rounded-r-none border-r-0': suffix, |
104 | | - })} |
105 | | - /> |
106 | | - </FormControl> |
107 | | - {suffix && <FieldSuffix>{suffix}</FieldSuffix>} |
108 | | - </div> |
109 | | - {description && <FormDescription Component={components?.FormDescription}>{description}</FormDescription>} |
110 | | - {fieldState.error && ( |
111 | | - <FormMessage Component={components?.FormMessage}>{fieldState.error.message}</FormMessage> |
112 | | - )} |
113 | | - </FormItem> |
114 | | - ); |
115 | | - }} |
116 | | - /> |
117 | | - ); |
118 | | -}; |
| 72 | + return ( |
| 73 | + <FormField |
| 74 | + control={control} |
| 75 | + name={name} |
| 76 | + render={({ field, fieldState }) => { |
| 77 | + return ( |
| 78 | + <FormItem className={className}> |
| 79 | + {label && <FormLabel Component={components?.FormLabel}>{label}</FormLabel>} |
| 80 | + <div |
| 81 | + className={cn('flex group transition-all duration-200 rounded-md', { |
| 82 | + 'field__input--with-prefix': prefix, |
| 83 | + 'field__input--with-suffix': suffix, |
| 84 | + 'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background': true, |
| 85 | + })} |
| 86 | + > |
| 87 | + {prefix && <FieldPrefix>{prefix}</FieldPrefix>} |
| 88 | + <FormControl Component={components?.FormControl}> |
| 89 | + <InputComponent |
| 90 | + {...field} |
| 91 | + {...props} |
| 92 | + ref={ref} |
| 93 | + className={cn('focus-visible:ring-0 focus-visible:ring-offset-0 border-input', { |
| 94 | + 'rounded-l-none border-l-0': prefix, |
| 95 | + 'rounded-r-none border-r-0': suffix, |
| 96 | + })} |
| 97 | + /> |
| 98 | + </FormControl> |
| 99 | + {suffix && <FieldSuffix>{suffix}</FieldSuffix>} |
| 100 | + </div> |
| 101 | + {description && <FormDescription Component={components?.FormDescription}>{description}</FormDescription>} |
| 102 | + {fieldState.error && ( |
| 103 | + <FormMessage Component={components?.FormMessage}>{fieldState.error.message}</FormMessage> |
| 104 | + )} |
| 105 | + </FormItem> |
| 106 | + ); |
| 107 | + }} |
| 108 | + /> |
| 109 | + ); |
| 110 | + }, |
| 111 | +); |
119 | 112 |
|
120 | 113 | TextField.displayName = 'TextField'; |
0 commit comments