Skip to content

Commit 3e68698

Browse files
committed
feat: add filter on create option and extend type
1 parent 42324b3 commit 3e68698

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

src/Shared/Components/SelectPicker/SelectPicker.component.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { ReactComponent as ICInfoFilledOverride } from '@Icons/ic-info-filled-ov
3131
import { ComponentSizeType } from '@Shared/constants'
3232
import { ConditionalWrap } from '@Common/Helper'
3333
import Tippy from '@tippyjs/react'
34-
import { getCommonSelectStyle } from './utils'
34+
import { getCommonSelectStyle, getSelectPickerOptionByValue } from './utils'
3535
import {
3636
SelectPickerMultiValueLabel,
3737
SelectPickerMultiValueRemove,
@@ -201,7 +201,7 @@ const SelectPicker = forwardRef(
201201
}: SelectPickerProps,
202202
ref: ForwardedRef<SelectInstance<SelectPickerOptionType>>,
203203
) => {
204-
const { inputId, required, isDisabled, controlShouldRenderValue } = props
204+
const { inputId, required, isDisabled, controlShouldRenderValue, value } = props
205205
const {
206206
isCreatable = false,
207207
isGroupHeadingSelectable = false,
@@ -230,7 +230,11 @@ const SelectPicker = forwardRef(
230230
)
231231

232232
// Used to show the create new option for creatable select
233-
const isValidNewOption = (inputValue: string) => isCreatable && !!inputValue?.trim()
233+
// TODO: FilterButton; Target Platform
234+
const isValidNewOption = (inputValue: string) =>
235+
isCreatable &&
236+
!!inputValue?.trim() &&
237+
!getSelectPickerOptionByValue(value as SelectPickerOptionType[], inputValue.trim(), null)
234238

235239
const renderControl = useCallback(
236240
(controlProps: ControlProps<SelectPickerOptionType>) => (

src/Shared/Components/SelectPicker/type.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
import { OptionType } from '@Common/Types'
1818
import { ComponentSizeType } from '@Shared/constants'
1919
import { ReactElement, ReactNode } from 'react'
20-
import { Props as ReactSelectProps } from 'react-select'
20+
import { GroupBase, Props as ReactSelectProps } from 'react-select'
21+
import { CreatableProps } from 'react-select/creatable'
2122

2223
export interface SelectPickerOptionType extends OptionType<number | string, ReactNode> {
2324
/**
@@ -39,7 +40,7 @@ export enum SelectPickerVariantType {
3940
BORDER_LESS = 'border-less',
4041
}
4142

42-
type SelectProps = ReactSelectProps<SelectPickerOptionType>
43+
type SelectProps = ReactSelectProps<SelectPickerOptionType, boolean, GroupBase<SelectPickerOptionType>>
4344

4445
export type SelectPickerProps = Pick<
4546
SelectProps,
@@ -138,7 +139,10 @@ export type SelectPickerProps = Pick<
138139
}
139140
| {
140141
isMulti: boolean
141-
multiSelectProps?: {
142+
multiSelectProps?: Pick<
143+
CreatableProps<SelectPickerOptionType, true, GroupBase<SelectPickerOptionType>>,
144+
'onCreateOption'
145+
> & {
142146
/**
143147
* If true, the select picker creates the new option
144148
* Only applicable for isMulti: true

src/Shared/Components/SelectPicker/utils.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import { CHECKBOX_VALUE } from '@Common/Types'
1818
import { ComponentSizeType } from '@Shared/constants'
19-
import { MultiValue, StylesConfig } from 'react-select'
19+
import { GroupBase, MultiValue, OptionsOrGroups, StylesConfig } from 'react-select'
2020
import { SelectPickerOptionType, SelectPickerProps, SelectPickerVariantType } from './type'
2121

2222
const getMenuWidthFromSize = (menuSize: SelectPickerProps['menuSize']): string => {
@@ -312,3 +312,39 @@ export const getGroupCheckboxValue = (
312312

313313
return null
314314
}
315+
316+
/**
317+
* Retrieves an option from the options list based on the provided value.
318+
*
319+
* @param optionsList - The list of options or groups of options.
320+
* @param value - The value to compare against the options' values.
321+
* @param defaultOption - The default option to return if no match is found.
322+
* @returns The matched option or the default option if no match is found.
323+
*/
324+
export const getSelectPickerOptionByValue = (
325+
optionsList: OptionsOrGroups<SelectPickerOptionType, GroupBase<SelectPickerOptionType>>,
326+
value: string | number,
327+
defaultOption: SelectPickerOptionType = { label: '', value: '' },
328+
): SelectPickerOptionType => {
329+
const foundOption = (optionsList ?? []).reduce(
330+
(acc, curr) => {
331+
if (!acc.notFound) return acc
332+
333+
if ('value' in curr && curr.value === value) {
334+
return { data: curr, notFound: false }
335+
}
336+
337+
if ('options' in curr && curr.options) {
338+
const nestedOption = curr.options.find(({ value: _value }) => _value === value)
339+
if (nestedOption) {
340+
return { data: nestedOption, notFound: false }
341+
}
342+
}
343+
344+
return acc
345+
},
346+
{ notFound: true, data: defaultOption },
347+
).data
348+
349+
return foundOption
350+
}

0 commit comments

Comments
 (0)