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