|
1 | | -import React, { forwardRef, ReactNode } from "react"; |
| 1 | +import React, { ReactNode } from "react"; |
2 | 2 | import { useField } from "formik"; |
3 | 3 | import ReactSelect, { |
4 | 4 | GroupBase, |
@@ -57,6 +57,7 @@ export type SelectProps< |
57 | 57 | label?: string; |
58 | 58 | theme?: Partial<SelectTheme>; |
59 | 59 | reactSelectTheme?: ReactSelectProps<Option, IsMulti, Group>["theme"]; |
| 60 | + selectRef?: Parameters<typeof ReactSelect<Option, IsMulti, Group>>[0]["ref"]; |
60 | 61 | }; |
61 | 62 |
|
62 | 63 | // Custom styles function with proper typing |
@@ -191,96 +192,92 @@ export type DefaultSelectProps<IsMulti extends boolean = false> = SelectProps< |
191 | 192 | IsMulti, |
192 | 193 | GroupBase<SelectOption> |
193 | 194 | >; |
194 | | -export const Select = forwardRef( |
195 | | - < |
196 | | - Option extends SelectOption = SelectOption, |
197 | | - IsMulti extends boolean = false, |
198 | | - Group extends GroupBase<Option> = GroupBase<Option> |
199 | | - >( |
200 | | - { |
201 | | - name, |
202 | | - options, |
203 | | - placeholder = "Choose...", |
204 | | - isClearable = false, |
205 | | - isSearchable = true, |
206 | | - isDisabled = false, |
207 | | - errorMessage, |
208 | | - onChange, |
209 | | - onBlur, |
210 | | - theme, |
211 | | - reactSelectTheme, |
212 | | - isMulti, |
213 | | - ...props |
214 | | - }: SelectProps<Option, IsMulti, Group>, |
215 | | - ref: Parameters<typeof ReactSelect<Option, IsMulti, Group>>[0]["ref"] |
216 | | - ) => { |
217 | | - const [field, meta, helpers] = |
218 | | - useField<IsMulti extends true ? MultiValue<Option> : SingleValue<Option>>( |
219 | | - name |
220 | | - ); |
| 195 | +export function Select< |
| 196 | + Option extends SelectOption = SelectOption, |
| 197 | + IsMulti extends boolean = false, |
| 198 | + Group extends GroupBase<Option> = GroupBase<Option> |
| 199 | +>({ |
| 200 | + name, |
| 201 | + options, |
| 202 | + placeholder = "Choose...", |
| 203 | + isClearable = false, |
| 204 | + isSearchable = true, |
| 205 | + isDisabled = false, |
| 206 | + errorMessage, |
| 207 | + onChange, |
| 208 | + onBlur, |
| 209 | + theme, |
| 210 | + reactSelectTheme, |
| 211 | + isMulti, |
| 212 | + selectRef, |
| 213 | + ...props |
| 214 | +}: SelectProps<Option, IsMulti, Group>) { |
| 215 | + const [field, meta, helpers] = |
| 216 | + useField<IsMulti extends true ? MultiValue<Option> : SingleValue<Option>>( |
| 217 | + name |
| 218 | + ); |
221 | 219 |
|
222 | | - const displayErrorMessage = |
223 | | - meta.error && meta.touched && !errorMessage |
224 | | - ? meta.error |
225 | | - : meta.error && meta.touched && errorMessage |
226 | | - ? errorMessage |
227 | | - : ""; |
| 220 | + const displayErrorMessage = |
| 221 | + meta.error && meta.touched && !errorMessage |
| 222 | + ? meta.error |
| 223 | + : meta.error && meta.touched && errorMessage |
| 224 | + ? errorMessage |
| 225 | + : ""; |
228 | 226 |
|
229 | | - const displayError = |
230 | | - typeof displayErrorMessage === "string" && displayErrorMessage !== ""; |
| 227 | + const displayError = |
| 228 | + typeof displayErrorMessage === "string" && displayErrorMessage !== ""; |
231 | 229 |
|
232 | | - const handleChange = ( |
233 | | - option: IsMulti extends true ? MultiValue<Option> : SingleValue<Option>, |
234 | | - actionMeta: ActionMeta<Option> |
235 | | - ) => { |
236 | | - if (isDisabled) { |
237 | | - return; |
238 | | - } |
239 | | - if (!meta.touched) { |
240 | | - helpers.setTouched(true); |
241 | | - } |
242 | | - helpers.setValue(option); |
243 | | - onChange?.(option, actionMeta); |
244 | | - }; |
| 230 | + const handleChange = ( |
| 231 | + option: IsMulti extends true ? MultiValue<Option> : SingleValue<Option>, |
| 232 | + actionMeta: ActionMeta<Option> |
| 233 | + ) => { |
| 234 | + if (isDisabled) { |
| 235 | + return; |
| 236 | + } |
| 237 | + if (!meta.touched) { |
| 238 | + helpers.setTouched(true); |
| 239 | + } |
| 240 | + helpers.setValue(option); |
| 241 | + onChange?.(option, actionMeta); |
| 242 | + }; |
245 | 243 |
|
246 | | - const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => { |
247 | | - if (!meta.touched) { |
248 | | - helpers.setTouched(true); |
249 | | - } |
250 | | - field.onBlur(event); |
251 | | - onBlur?.(event); |
252 | | - }; |
| 244 | + const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => { |
| 245 | + if (!meta.touched) { |
| 246 | + helpers.setTouched(true); |
| 247 | + } |
| 248 | + field.onBlur(event); |
| 249 | + onBlur?.(event); |
| 250 | + }; |
253 | 251 |
|
254 | | - const { selectClassName } = useFixSelectFont({ |
255 | | - selectClassName: "boson-select", |
256 | | - hasError: displayError |
257 | | - }); |
| 252 | + const { selectClassName } = useFixSelectFont({ |
| 253 | + selectClassName: "boson-select", |
| 254 | + hasError: displayError |
| 255 | + }); |
258 | 256 |
|
259 | | - return ( |
260 | | - <> |
261 | | - <ReactSelect<Option, IsMulti, Group> |
262 | | - ref={ref} |
263 | | - styles={customStyles<Option, IsMulti, Group>( |
264 | | - displayErrorMessage, |
265 | | - theme |
266 | | - )} |
267 | | - {...field} |
268 | | - {...props} |
269 | | - theme={reactSelectTheme} |
270 | | - className={selectClassName} |
271 | | - isMulti={isMulti} |
272 | | - placeholder={placeholder} |
273 | | - options={options} |
274 | | - value={field.value} |
275 | | - onChange={handleChange} |
276 | | - onBlur={handleBlur} |
277 | | - isSearchable={isSearchable} |
278 | | - isClearable={isClearable} |
279 | | - isDisabled={isDisabled} |
280 | | - isOptionDisabled={(option) => !!option.disabled} |
281 | | - /> |
282 | | - <Error display={displayError} message={displayErrorMessage} /> |
283 | | - </> |
284 | | - ); |
285 | | - } |
286 | | -); |
| 257 | + return ( |
| 258 | + <> |
| 259 | + <ReactSelect<Option, IsMulti, Group> |
| 260 | + ref={selectRef} |
| 261 | + styles={customStyles<Option, IsMulti, Group>( |
| 262 | + displayErrorMessage, |
| 263 | + theme |
| 264 | + )} |
| 265 | + {...field} |
| 266 | + {...props} |
| 267 | + theme={reactSelectTheme} |
| 268 | + className={selectClassName} |
| 269 | + isMulti={isMulti} |
| 270 | + placeholder={placeholder} |
| 271 | + options={options} |
| 272 | + value={field.value} |
| 273 | + onChange={handleChange} |
| 274 | + onBlur={handleBlur} |
| 275 | + isSearchable={isSearchable} |
| 276 | + isClearable={isClearable} |
| 277 | + isDisabled={isDisabled} |
| 278 | + isOptionDisabled={(option) => !!option.disabled} |
| 279 | + /> |
| 280 | + <Error display={displayError} message={displayErrorMessage} /> |
| 281 | + </> |
| 282 | + ); |
| 283 | +} |
0 commit comments