From c6595a6e7c51dba17e7fb181bbb3be7b2924924c Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Wed, 12 Oct 2022 17:12:01 +0530 Subject: [PATCH 1/8] changed the value type --- docs/docs/components/select.mdx | 38 ++++---- lib/src/components/Select/Select.tsx | 107 ++++++++++++---------- lib/src/components/Select/select.types.ts | 4 +- 3 files changed, 78 insertions(+), 71 deletions(-) diff --git a/docs/docs/components/select.mdx b/docs/docs/components/select.mdx index 706a4ea..c89e468 100644 --- a/docs/docs/components/select.mdx +++ b/docs/docs/components/select.mdx @@ -244,25 +244,25 @@ const options = [ ### Props Reference -| Attributes | Values | Default Value | Optional ? | -| :---------------- | :-----------------------------------------------------------------------------------------------------: | :--------------: | ---------: | -| placeholder | `string` | `Pick one` | Yes | -| options | `Array of` **_Option Object_** | | No | -| value | `string` | `number`
when isMulti is `true` then value is
`(string` | ` number)[]` | | Yes | -| isMulti | `boolean` | `false` | Yes | -| color | `string` | `#2F80ED` | Yes | -| width | `string` | `100%` | Yes | -| isSearchable | `boolean` | `false` | Yes | -| error | `boolean` | `false` | Yes | -| maxDropDownHeight | `string` | `auto` | Yes | -| borderRadius | `string` | `0` | Yes | -| onChange | `(selectedOption,event)=>void` | `()=>{}` | Yes | -| isDisabled | `boolean` | `false` | Yes | -| isClearable | `boolean` | `false` | Yes | -| nothingFoundLabel | `string` | `JSX Element` | `Nothing Found!` | Yes | -| DropIcon | `JSX Element` | | Yes | -| onDropDownOpen | `()=> void ` | | Yes | -| onDropDownClose | `()=> void ` | | Yes | +| Attributes | Values | Default Value | Optional ? | +| :---------------- | :-------------------------------------------------------------------------------------------------------------------------------------: | :--------------: | ---------: | +| placeholder | `string` | `Pick one` | Yes | +| options | `Array of` **_[Options Object](#option-object)_** | | No | +| value | **_[Options Object](#option-object)_**
when isMulti is `true` then value is
Array of **_[Options Object](#option-object)_** | | Yes | +| isMulti | `boolean` | `false` | Yes | +| color | `string` | `#2F80ED` | Yes | +| width | `string` | `100%` | Yes | +| isSearchable | `boolean` | `false` | Yes | +| error | `boolean` | `false` | Yes | +| maxDropDownHeight | `string` | `auto` | Yes | +| borderRadius | `string` | `0` | Yes | +| onChange | `(selectedOption,event)=>void` | `()=>{}` | Yes | +| isDisabled | `boolean` | `false` | Yes | +| isClearable | `boolean` | `false` | Yes | +| nothingFoundLabel | `string` | `JSX Element` | `Nothing Found!` | Yes | +| DropIcon | `JSX Element` | | Yes | +| onDropDownOpen | `()=> void ` | | Yes | +| onDropDownClose | `()=> void ` | | Yes | ### Option Object diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index a74f015..c2b6e09 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -59,8 +59,8 @@ const SelectComponent: ForwardRefRenderFunction< ref ) => { const [selectValue, setSelectValue] = useState< - string | number | (string | number)[] | undefined - >(value); + OptionsType | OptionsType[] | null + >(value!); const [isDropped, setIsDropped] = useState(false); const [internalOptions, setInternalOptions] = useState(options); const [searchText, setSearchText] = useState(""); @@ -77,13 +77,17 @@ const SelectComponent: ForwardRefRenderFunction< useEffect(() => { if (isMulti) { - typeof selectValue === "object" && + Array.isArray(selectValue) && setInternalOptions( - options.filter((option) => !selectValue.includes(option.value)) + options.filter( + (option) => !selectValue.find((data) => data.value === option.value) + ) ); } else { setInternalOptions(options); - setSearchText(getLabel()); + selectValue + ? !Array.isArray(selectValue) && setSearchText(selectValue?.label) + : setSearchText(""); } }, [selectValue, isMulti]); @@ -118,13 +122,6 @@ const SelectComponent: ForwardRefRenderFunction< } }, [isDropped]); - const getLabel = (extValue?: string | number) => { - return ( - options.find((option) => option.value === (extValue || selectValue)) - ?.label || "" - ); - }; - const focusElement = (pointer: number) => { const optionsList = getOptionsRefAsArray(); optionsList?.map((option, index) => { @@ -157,23 +154,24 @@ const SelectComponent: ForwardRefRenderFunction< ) => { if (isMulti) { setSearchText(""); - const multiValue = - typeof selectValue === "object" ? [...selectValue] : []; - multiValue.push(option.value); - if (value !== undefined) { - onChange(multiValue, event); - } else { - setSelectValue(multiValue); - } + const multiValue = Array.isArray(selectValue) ? [...selectValue] : []; + multiValue.push(option); + onChange(multiValue, event); + setSelectValue(multiValue); } else { - if (value !== undefined) { - isClearable && option.value === selectValue - ? onChange("", event) - : onChange(option.value, event); + isClearable && + !Array.isArray(selectValue) && + option.value === selectValue?.value; + if ( + isClearable && + !Array.isArray(selectValue) && + option.value === selectValue?.value + ) { + setSelectValue(null); + onChange(null, event); } else { - isClearable && option.value === selectValue - ? setSelectValue("") - : setSelectValue(option.value); + setSelectValue(option); + onChange(option, event); } setIsDropped(false); setInternalOptions(options); @@ -185,8 +183,10 @@ const SelectComponent: ForwardRefRenderFunction< event.stopPropagation(); const text = event.target.value; const mainOptions = - isMulti && typeof selectValue === "object" - ? options.filter((option) => !selectValue.includes(option.value)) + isMulti && Array.isArray(selectValue) + ? options.filter( + (option) => !selectValue.find((data) => data.value === option.value) + ) : options; setIsDropped(true); setSearchText(text); @@ -204,10 +204,12 @@ const SelectComponent: ForwardRefRenderFunction< const handleIconClick = (event: MouseEvent) => { event.stopPropagation(); if (isClearable) { - if (value !== undefined) { - isMulti ? onChange([], event) : onChange("", event); + if (isMulti) { + onChange([], event); + setSelectValue([]); } else { - isMulti ? setSelectValue([]) : setSelectValue(""); + onChange(null, event); + setSelectValue(null); } } else { setIsDropped(!isDropped); @@ -224,21 +226,18 @@ const SelectComponent: ForwardRefRenderFunction< clearValue: string | number, event: MouseEvent | KeyboardEvent ) => { - let tempArr = typeof selectValue === "object" ? [...selectValue] : []; - tempArr = tempArr.filter((arr) => arr !== clearValue); - if (value !== undefined) { - onChange(tempArr, event); - } else { - setSelectValue(tempArr); - } + let tempArr = Array.isArray(selectValue) ? [...selectValue] : []; + tempArr = tempArr.filter((arr) => arr.value !== clearValue); + onChange(tempArr, event); + setSelectValue(tempArr); setIsDropped(true); }; const checkIfAllValuesSelected = () => { return ( - typeof selectValue === "object" && + Array.isArray(selectValue) && selectValue.length === options.length && - options.every((el) => selectValue.includes(el.value)) + options.every((el) => selectValue.find((data) => data.value === el.value)) ); }; @@ -274,10 +273,10 @@ const SelectComponent: ForwardRefRenderFunction< isMulti && event.code === "Backspace" && searchText === "" && - typeof selectValue === "object" + Array.isArray(selectValue) ) { let lastValue = selectValue[selectValue.length - 1]; - clearPill(lastValue, event); + clearPill(lastValue?.value, event); } if (event.key === "Enter" || event.code === "Space") { @@ -420,12 +419,13 @@ const SelectComponent: ForwardRefRenderFunction< alignItems="center" > {isMulti && - (typeof selectValue === "object" && selectValue.length !== 0 - ? selectValue?.map((arr) => { + (Array.isArray(selectValue) && selectValue.length !== 0 + ? selectValue?.map((arr, ind) => { return ( clearPill(arr, event)} + key={ind} + value={arr.label} + clearValue={(event) => clearPill(arr.value, event)} /> ); }) @@ -446,7 +446,8 @@ const SelectComponent: ForwardRefRenderFunction< )} {!isMulti && !isSearchable && - (getLabel() || ( + !Array.isArray(selectValue) && + (selectValue?.label || (
{placeholder || "Pick one"}
@@ -476,7 +477,10 @@ const SelectComponent: ForwardRefRenderFunction< internalOptions.map((option, ind) => { const selectListClass = selectListRecipe({ disabled: option.disabled, - active: !isMulti && option.value === selectValue, + active: + !isMulti && + !Array.isArray(selectValue) && + option.value === selectValue?.value, }); return (
!option.disabled && internalClickHandler(option, event) diff --git a/lib/src/components/Select/select.types.ts b/lib/src/components/Select/select.types.ts index ecc65b9..021d6ca 100644 --- a/lib/src/components/Select/select.types.ts +++ b/lib/src/components/Select/select.types.ts @@ -3,10 +3,10 @@ type divType = Omit; export type SelectPropsType = divType & { placeholder?: string; options: OptionsType[]; - value?: string | number | (string | number)[]; + value?: OptionsType | OptionsType[] | null; width?: string; onChange?: ( - value: string | number | (string | number)[], + value: OptionsType | OptionsType[] | null, event?: | MouseEvent | KeyboardEvent From 658c6320b22b2defa236f8f2cbb58d70dde60bec Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Wed, 12 Oct 2022 17:20:42 +0530 Subject: [PATCH 2/8] minor bug fix --- lib/src/components/Select/Select.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index c2b6e09..ecd2d22 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -159,9 +159,6 @@ const SelectComponent: ForwardRefRenderFunction< onChange(multiValue, event); setSelectValue(multiValue); } else { - isClearable && - !Array.isArray(selectValue) && - option.value === selectValue?.value; if ( isClearable && !Array.isArray(selectValue) && From 8d59e30d781a09b6efa767ebf9dee2fc1be6a8b9 Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Wed, 12 Oct 2022 17:23:35 +0530 Subject: [PATCH 3/8] code smell removed --- lib/src/components/Select/Select.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index ecd2d22..08b3e33 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -60,7 +60,7 @@ const SelectComponent: ForwardRefRenderFunction< ) => { const [selectValue, setSelectValue] = useState< OptionsType | OptionsType[] | null - >(value!); + >(null); const [isDropped, setIsDropped] = useState(false); const [internalOptions, setInternalOptions] = useState(options); const [searchText, setSearchText] = useState(""); From 6705b8ae82afbe7037c8bb6869dbf229aa298fbc Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Thu, 20 Oct 2022 13:50:35 +0530 Subject: [PATCH 4/8] options not re rendering fix --- lib/src/components/Select/Select.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index 08b3e33..dece4af 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -89,7 +89,7 @@ const SelectComponent: ForwardRefRenderFunction< ? !Array.isArray(selectValue) && setSearchText(selectValue?.label) : setSearchText(""); } - }, [selectValue, isMulti]); + }, [selectValue, isMulti, options]); useEffect(() => { focusElement(cursor); From 0f4ccfe92e3f52ad8bba0abeb6af9bb004a77606 Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Thu, 20 Oct 2022 14:39:41 +0530 Subject: [PATCH 5/8] handled options when undefined --- lib/src/components/Select/Select.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index dece4af..a506139 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -96,7 +96,7 @@ const SelectComponent: ForwardRefRenderFunction< }, [cursor]); useEffect(() => { - if (internalOptions.length !== 0) { + if (Array.isArray(internalOptions)) { let skipCount = cursor; while (internalOptions[skipCount]?.disabled) { skipCount++; @@ -470,7 +470,7 @@ const SelectComponent: ForwardRefRenderFunction< className={`${selectListContainerStyle}`} role={"listbox"} > - {internalOptions.length !== 0 ? ( + {Array.isArray(internalOptions) ? ( internalOptions.map((option, ind) => { const selectListClass = selectListRecipe({ disabled: option.disabled, From bd5e41b098a416d507c95f57f771309ccb69ea57 Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Thu, 20 Oct 2022 15:26:29 +0530 Subject: [PATCH 6/8] minor changes --- lib/src/components/Select/Select.tsx | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index a506139..db1b38b 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -77,12 +77,14 @@ const SelectComponent: ForwardRefRenderFunction< useEffect(() => { if (isMulti) { - Array.isArray(selectValue) && - setInternalOptions( - options.filter( - (option) => !selectValue.find((data) => data.value === option.value) + Array.isArray(selectValue) + ? setInternalOptions( + options?.filter( + (option) => + !selectValue.find((data) => data.value === option.value) + ) ) - ); + : setInternalOptions(options); } else { setInternalOptions(options); selectValue @@ -181,13 +183,13 @@ const SelectComponent: ForwardRefRenderFunction< const text = event.target.value; const mainOptions = isMulti && Array.isArray(selectValue) - ? options.filter( + ? options?.filter( (option) => !selectValue.find((data) => data.value === option.value) ) : options; setIsDropped(true); setSearchText(text); - const filteredOptions = mainOptions.filter((option) => { + const filteredOptions = mainOptions?.filter((option) => { return option.label .trim() .toLowerCase() @@ -233,6 +235,7 @@ const SelectComponent: ForwardRefRenderFunction< const checkIfAllValuesSelected = () => { return ( Array.isArray(selectValue) && + Array.isArray(options) && selectValue.length === options.length && options.every((el) => selectValue.find((data) => data.value === el.value)) ); @@ -416,7 +419,7 @@ const SelectComponent: ForwardRefRenderFunction< alignItems="center" > {isMulti && - (Array.isArray(selectValue) && selectValue.length !== 0 + (Array.isArray(selectValue) ? selectValue?.map((arr, ind) => { return ( - {Array.isArray(internalOptions) ? ( + {Array.isArray(internalOptions) && internalOptions?.length !== 0 ? ( internalOptions.map((option, ind) => { const selectListClass = selectListRecipe({ disabled: option.disabled, From 52d1d944c2fa0e21d12d0f2bd324e27ee6819756 Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Thu, 20 Oct 2022 15:44:32 +0530 Subject: [PATCH 7/8] keyboard controls error on undefined fix --- lib/src/components/Select/Select.tsx | 71 ++++++++++++++++------------ 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index db1b38b..a2fc41d 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -288,7 +288,7 @@ const SelectComponent: ForwardRefRenderFunction< if (isDropped) { optionsList?.map((option) => { if (option.getAttribute("data-hover") === "true") { - const optionValue = internalOptions.find( + const optionValue = internalOptions?.find( (arr) => arr.value === option.getAttribute("data-value") ) as OptionsType; !optionValue.disabled && internalClickHandler(optionValue, event); @@ -301,51 +301,60 @@ const SelectComponent: ForwardRefRenderFunction< }; const focusNextOption = () => { - let skipStep = 1; - while ( + if (Array.isArray(internalOptions)) { + let skipStep = 1; + while ( + cursor + skipStep < internalOptions.length && + internalOptions[cursor + skipStep].disabled + ) { + skipStep++; + } cursor + skipStep < internalOptions.length && - internalOptions[cursor + skipStep].disabled - ) { - skipStep++; + setCursor(cursor + skipStep); } - cursor + skipStep < internalOptions.length && setCursor(cursor + skipStep); }; const focusPrevOption = () => { - let skipStep = 1; - while ( - cursor - skipStep >= 0 && - internalOptions[cursor - skipStep].disabled - ) { - skipStep++; + if (Array.isArray(internalOptions)) { + let skipStep = 1; + while ( + cursor - skipStep >= 0 && + internalOptions[cursor - skipStep].disabled + ) { + skipStep++; + } + cursor - skipStep >= 0 && setCursor(cursor - skipStep); } - cursor - skipStep >= 0 && setCursor(cursor - skipStep); }; const focusFirstOption = () => { - let skipStep = 0; - while ( - skipStep < internalOptions.length && - internalOptions[skipStep].disabled - ) { - skipStep++; - } - if (skipStep < internalOptions.length) { - setCursor(skipStep); - focusElement(skipStep); + if (Array.isArray(internalOptions)) { + let skipStep = 0; + while ( + skipStep < internalOptions.length && + internalOptions[skipStep].disabled + ) { + skipStep++; + } + if (skipStep < internalOptions.length) { + setCursor(skipStep); + focusElement(skipStep); + } } }; const focusLastOption = () => { - let skipStep = 1; - while ( + if (Array.isArray(internalOptions)) { + let skipStep = 1; + while ( + internalOptions.length - skipStep >= 0 && + internalOptions[internalOptions.length - skipStep].disabled + ) { + skipStep++; + } internalOptions.length - skipStep >= 0 && - internalOptions[internalOptions.length - skipStep].disabled - ) { - skipStep++; + setCursor(internalOptions.length - skipStep); } - internalOptions.length - skipStep >= 0 && - setCursor(internalOptions.length - skipStep); }; const inputKeyDownHandler = (event: KeyboardEvent) => { From 664c7e8b0816e7cf2936d793c93cc838d26022cc Mon Sep 17 00:00:00 2001 From: saurabhsutar192 Date: Thu, 20 Oct 2022 16:14:06 +0530 Subject: [PATCH 8/8] keyboard control bug fix --- lib/src/components/Select/Select.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/components/Select/Select.tsx b/lib/src/components/Select/Select.tsx index a2fc41d..0311221 100644 --- a/lib/src/components/Select/Select.tsx +++ b/lib/src/components/Select/Select.tsx @@ -289,9 +289,10 @@ const SelectComponent: ForwardRefRenderFunction< optionsList?.map((option) => { if (option.getAttribute("data-hover") === "true") { const optionValue = internalOptions?.find( - (arr) => arr.value === option.getAttribute("data-value") + (arr) => + JSON.stringify(arr.value) === option.getAttribute("data-value") ) as OptionsType; - !optionValue.disabled && internalClickHandler(optionValue, event); + !optionValue?.disabled && internalClickHandler(optionValue, event); } }); } else if (!isDropped) {