Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
IR-2018 Refactor the Select component to disable search functionality…
Browse files Browse the repository at this point in the history
… for the dropdown only (#10206)

* Refactor Select component to include onBlur event handler

* Hanzla changes

* Commented out handleKeyDown function in Select component

* Add dropDownOnly prop to Input component

* Add dropDownOnly prop to Select component

* Refactor input and select components

* Restored if condition as before

---------

Co-authored-by: hanzlamateen <[email protected]>
  • Loading branch information
hurairahmateen and hanzlamateen authored May 22, 2024
1 parent 6668a44 commit 081c6bf
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default function AddEditUserModal({ user }: { user?: UserType }) {
action: 'admin'
}
})
const avatarOptions: SelectOptionsType =
const avatarOptions: SelectOptionsType[] =
avatarsQuery.status === 'success'
? [
{ label: t('admin:components.user.selectAvatar'), value: '', disabled: true },
Expand All @@ -71,7 +71,7 @@ export default function AddEditUserModal({ user }: { user?: UserType }) {
paginate: false
}
})
const scopeTypeOptions: SelectOptionsType =
const scopeTypeOptions: SelectOptionsType[] =
scopeTypesQuery.status === 'success'
? [
{ label: t('admin:components.user.selectScopes'), value: '', disabled: true },
Expand Down
68 changes: 43 additions & 25 deletions packages/ui/src/primitives/tailwind/Select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ import Input from '../Input'

export type OptionValueType = string | number

export type SelectOptionsType = { label: string; value: any; disabled?: boolean }[]
export type SelectOptionsType = { label: string; value: any; disabled?: boolean }

export interface SelectProps<T extends OptionValueType> {
label?: string
className?: string
error?: string
description?: string
options: { label: string; value: T; disabled?: boolean }[]
options: SelectOptionsType[]
currentValue: T
onChange: (value: T) => void
placeholder?: string
Expand All @@ -53,6 +53,7 @@ export interface SelectProps<T extends OptionValueType> {
inputVariant?: 'outlined' | 'underlined' | 'onboarding'
inputClassName?: string
errorBorder?: boolean
searchDisabled?: boolean
}

const Select = <T extends OptionValueType>({
Expand All @@ -70,39 +71,59 @@ const Select = <T extends OptionValueType>({
labelClassName,
inputVariant,
inputClassName,
errorBorder
errorBorder,
searchDisabled
}: SelectProps<T>) => {
const ref = useRef<HTMLDivElement>(null)
const { t } = useTranslation()

const showOptions = useHookstate(false)
const filteredOptions = useHookstate(options)
const selectLabel = useHookstate('')

useClickOutside(ref, () => showOptions.set(false))

useEffect(() => {
const labelName = options.find((option) => option.value === currentValue)?.label
if (labelName) selectLabel.set(labelName || '')
}, [currentValue, options])

const toggleDropdown = () => {
showOptions.set((v) => !v)
}
useEffect(() => {
filteredOptions.set(options)
}, [options])

const toggleDropdown = () => {
showOptions.set((v) => !v)
}

// Prevent the input field from receiving focus with Mouse click when it is searchDisabled
const handleMouseDown = (e: React.MouseEvent) => {
if (searchDisabled) {
e.preventDefault()
}
}

const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
selectLabel.set(e.target.value)
const newOptions: SelectProps<T>['options'] = []
for (let i = 0; i < options.length; i++) {
if (options[i].label.toLowerCase().startsWith(e.target.value.toLowerCase())) {
newOptions.push(options[i])
}
if (searchDisabled) {
return
}
const newOptions = options.filter((item) => item.label.toLowerCase().startsWith(e.target.value.toLowerCase()))
if (newOptions.length > 0) {
filteredOptions.set(newOptions)
selectLabel.set(e.target.value)
}

const optionFound = options.find((item) => item.label === e.target.value)
if (optionFound) {
onChange(newOptions[0].value as T)
}
filteredOptions.set(newOptions)
}

const selectLabel = useHookstate('')
useEffect(() => {
const labelName = options.find((option) => option.value === currentValue)?.label
if (labelName) selectLabel.set(labelName)
}, [currentValue, options])
const handleOptionItem = (option: SelectOptionsType) => {
if (option.disabled) return

useClickOutside(ref, () => showOptions.set(false))
showOptions.set(false)
onChange(option.value as T)
}

return (
<div className={twMerge('relative', className)} ref={ref}>
Expand All @@ -119,6 +140,7 @@ const Select = <T extends OptionValueType>({
value={selectLabel.value}
onChange={handleSearch}
onClick={toggleDropdown}
onMouseDown={handleMouseDown}
/>
<MdOutlineKeyboardArrowDown
size="1.5em"
Expand All @@ -142,11 +164,7 @@ const Select = <T extends OptionValueType>({
option.disabled ? 'cursor-not-allowed' : 'hover:text-theme-highlight hover:bg-theme-highlight',
menuItemClassName
)}
onClick={() => {
if (option.disabled) return
showOptions.set(false)
onChange(option.value as T)
}}
onClick={() => handleOptionItem(option)}
>
{option.label}
</li>
Expand Down

0 comments on commit 081c6bf

Please sign in to comment.