1
- import ReactSelect , { ControlProps , MenuListProps , OptionProps , ValueContainerProps } from 'react-select'
1
+ import ReactSelect , {
2
+ ControlProps ,
3
+ GroupHeadingProps ,
4
+ MenuListProps ,
5
+ MultiValueProps ,
6
+ OptionProps ,
7
+ ValueContainerProps ,
8
+ } from 'react-select'
9
+ import CreatableSelect from 'react-select/creatable'
2
10
import { ReactElement , useCallback , useMemo } from 'react'
3
11
import { ReactComponent as ErrorIcon } from '@Icons/ic-warning.svg'
4
12
import { ReactComponent as ICInfoFilledOverride } from '@Icons/ic-info-filled-override.svg'
@@ -7,9 +15,12 @@ import { ConditionalWrap } from '@Common/Helper'
7
15
import Tippy from '@tippyjs/react'
8
16
import { getCommonSelectStyle } from './utils'
9
17
import {
18
+ MultiValueLabel ,
19
+ MultiValueRemove ,
10
20
SelectPickerClearIndicator ,
11
21
SelectPickerControl ,
12
22
SelectPickerDropdownIndicator ,
23
+ SelectPickerGroupHeading ,
13
24
SelectPickerLoadingIndicator ,
14
25
SelectPickerMenuList ,
15
26
SelectPickerOption ,
@@ -112,9 +123,16 @@ const SelectPicker = ({
112
123
menuSize,
113
124
variant = SelectPickerVariantType . DEFAULT ,
114
125
disableDescriptionEllipsis = false ,
126
+ getIsOptionValid = ( ) => true ,
127
+ isCreatable = false ,
128
+ isGroupHeadingSelectable = false ,
129
+ isMulti,
115
130
...props
116
131
} : SelectPickerProps ) => {
117
- const { inputId, required, isDisabled } = props
132
+ const { inputId, required, isDisabled, controlShouldRenderValue } = props
133
+ // Only large variant is supported for multi select picker
134
+ const selectSize = isMulti && ! controlShouldRenderValue ? ComponentSizeType . large : size
135
+ const shouldShowSelectedOptionIcon = ! isMulti && showSelectedOptionIcon
118
136
119
137
const labelId = `${ inputId } -label`
120
138
const errorElementId = `${ inputId } -error-msg`
@@ -123,18 +141,22 @@ const SelectPicker = ({
123
141
( ) =>
124
142
getCommonSelectStyle ( {
125
143
error,
126
- size,
144
+ size : selectSize ,
127
145
menuSize,
128
146
variant,
147
+ getIsOptionValid,
148
+ isGroupHeadingSelectable,
129
149
} ) ,
130
- [ error , size , menuSize , variant ] ,
150
+ [ error , selectSize , menuSize , variant , isGroupHeadingSelectable ] ,
131
151
)
132
152
153
+ const isValidNewOption = ( inputValue : string ) => isCreatable && ! ! inputValue ?. trim ( )
154
+
133
155
const renderControl = useCallback (
134
156
( controlProps : ControlProps < SelectPickerOptionType > ) => (
135
- < SelectPickerControl { ...controlProps } icon = { icon } showSelectedOptionIcon = { showSelectedOptionIcon } />
157
+ < SelectPickerControl { ...controlProps } icon = { icon } showSelectedOptionIcon = { shouldShowSelectedOptionIcon } />
136
158
) ,
137
- [ icon , showSelectedOptionIcon ] ,
159
+ [ icon , shouldShowSelectedOptionIcon ] ,
138
160
)
139
161
140
162
const renderMenuList = useCallback (
@@ -146,7 +168,7 @@ const SelectPicker = ({
146
168
147
169
const renderValueContainer = useCallback (
148
170
( valueContainerProps : ValueContainerProps < SelectPickerOptionType > ) => (
149
- < SelectPickerValueContainer { ...valueContainerProps } showSelectedOptionsCount = { false } />
171
+ < SelectPickerValueContainer { ...valueContainerProps } showSelectedOptionsCount = { showSelectedOptionsCount } />
150
172
) ,
151
173
[ showSelectedOptionsCount ] ,
152
174
)
@@ -158,6 +180,17 @@ const SelectPicker = ({
158
180
[ disableDescriptionEllipsis ] ,
159
181
)
160
182
183
+ const renderMultiValueLabel = ( multiValueLabelProps : MultiValueProps < SelectPickerOptionType , true > ) => (
184
+ < MultiValueLabel { ...multiValueLabelProps } getIsOptionValid = { getIsOptionValid } />
185
+ )
186
+
187
+ const renderGroupHeading = useCallback (
188
+ ( groupHeadingProps : GroupHeadingProps < SelectPickerOptionType > ) => (
189
+ < SelectPickerGroupHeading { ...groupHeadingProps } isGroupHeadingSelectable = { isGroupHeadingSelectable } />
190
+ ) ,
191
+ [ isGroupHeadingSelectable ] ,
192
+ )
193
+
161
194
const renderDisabledTippy = ( children : ReactElement ) => (
162
195
< Tippy content = { disabledTippyContent } placement = "top" className = "default-tt" arrow = { false } >
163
196
{ children }
@@ -187,29 +220,62 @@ const SelectPicker = ({
187
220
) }
188
221
< ConditionalWrap condition = { isDisabled && ! ! disabledTippyContent } wrap = { renderDisabledTippy } >
189
222
< div className = "w-100" >
190
- < ReactSelect < SelectPickerOptionType , boolean >
191
- { ...props }
192
- placeholder = { placeholder }
193
- components = { {
194
- IndicatorSeparator : null ,
195
- LoadingIndicator : SelectPickerLoadingIndicator ,
196
- DropdownIndicator : SelectPickerDropdownIndicator ,
197
- Control : renderControl ,
198
- Option : renderOption ,
199
- MenuList : renderMenuList ,
200
- ClearIndicator : SelectPickerClearIndicator ,
201
- ValueContainer : renderValueContainer ,
202
- } }
203
- styles = { selectStyles }
204
- menuPlacement = "auto"
205
- menuPosition = "fixed"
206
- menuShouldScrollIntoView
207
- backspaceRemovesValue = { false }
208
- aria-errormessage = { errorElementId }
209
- aria-invalid = { ! ! error }
210
- aria-labelledby = { labelId }
211
- hideSelectedOptions = { false }
212
- />
223
+ { isMulti ? (
224
+ < CreatableSelect < SelectPickerOptionType , true >
225
+ { ...props }
226
+ isMulti
227
+ placeholder = { placeholder }
228
+ components = { {
229
+ IndicatorSeparator : null ,
230
+ LoadingIndicator : SelectPickerLoadingIndicator ,
231
+ DropdownIndicator : SelectPickerDropdownIndicator ,
232
+ Control : renderControl ,
233
+ Option : renderOption ,
234
+ MenuList : renderMenuList ,
235
+ ClearIndicator : SelectPickerClearIndicator ,
236
+ ValueContainer : renderValueContainer ,
237
+ MultiValueLabel : renderMultiValueLabel ,
238
+ MultiValueRemove,
239
+ GroupHeading : renderGroupHeading ,
240
+ } }
241
+ styles = { selectStyles }
242
+ menuPlacement = "auto"
243
+ menuPosition = "fixed"
244
+ menuShouldScrollIntoView
245
+ backspaceRemovesValue
246
+ aria-errormessage = { errorElementId }
247
+ aria-invalid = { ! ! error }
248
+ aria-labelledby = { labelId }
249
+ closeMenuOnSelect = { false }
250
+ allowCreateWhileLoading = { false }
251
+ hideSelectedOptions = { false }
252
+ isValidNewOption = { isValidNewOption }
253
+ />
254
+ ) : (
255
+ < ReactSelect < SelectPickerOptionType , false >
256
+ { ...props }
257
+ placeholder = { placeholder }
258
+ components = { {
259
+ IndicatorSeparator : null ,
260
+ LoadingIndicator : SelectPickerLoadingIndicator ,
261
+ DropdownIndicator : SelectPickerDropdownIndicator ,
262
+ Control : renderControl ,
263
+ Option : renderOption ,
264
+ MenuList : renderMenuList ,
265
+ ClearIndicator : SelectPickerClearIndicator ,
266
+ ValueContainer : renderValueContainer ,
267
+ } }
268
+ styles = { selectStyles }
269
+ menuPlacement = "auto"
270
+ menuPosition = "fixed"
271
+ menuShouldScrollIntoView
272
+ backspaceRemovesValue = { false }
273
+ aria-errormessage = { errorElementId }
274
+ aria-invalid = { ! ! error }
275
+ aria-labelledby = { labelId }
276
+ hideSelectedOptions = { false }
277
+ />
278
+ ) }
213
279
</ div >
214
280
</ ConditionalWrap >
215
281
</ div >
0 commit comments