diff --git a/README.md b/README.md index 7f8bdb3..4dd05d3 100644 --- a/README.md +++ b/README.md @@ -305,8 +305,9 @@ searchControls={ minHeight: 10, paddingVertical: 10, paddingHorizontal: 5, - width: '50%', + width: '70%', textAlign: 'center', + backgroundColor: 'pink', }, textInputContainerStyle: { flex: 1, @@ -315,7 +316,7 @@ searchControls={ }, textInputProps: { placeholder: 'Search anything here', - placeholderTextColor: 'gray', + placeholderTextColor: 'white', }, } ``` diff --git a/example/ios/InputSelectExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/InputSelectExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/InputSelectExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/src/App.tsx b/example/src/App.tsx index 2e472ff..f2e55c0 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -98,8 +98,9 @@ export default function App() { minHeight: 10, paddingVertical: 10, paddingHorizontal: 5, - width: '50%', + width: '70%', textAlign: 'center', + backgroundColor: 'pink', }, textInputContainerStyle: { flex: 1, @@ -108,7 +109,7 @@ export default function App() { }, textInputProps: { placeholder: 'Search anything here', - placeholderTextColor: 'gray', + placeholderTextColor: 'white', }, }} /> diff --git a/src/components/CheckBox/index.tsx b/src/components/CheckBox/index.tsx index 8b447f7..15012cb 100644 --- a/src/components/CheckBox/index.tsx +++ b/src/components/CheckBox/index.tsx @@ -83,7 +83,7 @@ const CheckBox = ({ /> )} - {label && ( + {label && label !== '' && ( { - scrollToItem(listIndex.itemIndex); - }, [listIndex]); + if (options?.length) { + scrollToItem(listIndex.itemIndex); + } + }, [listIndex, options]); return ( `Options${index}`} diff --git a/src/components/Dropdown/DropdownSectionList.tsx b/src/components/Dropdown/DropdownSectionList.tsx index 0b5a48d..b64faa5 100644 --- a/src/components/Dropdown/DropdownSectionList.tsx +++ b/src/components/Dropdown/DropdownSectionList.tsx @@ -71,8 +71,10 @@ const DropdownSectionList = ({ }; useEffect(() => { - scrollToLocation(listIndex); - }, [listIndex]); + if (options?.length) { + scrollToLocation(listIndex); + } + }, [listIndex, options]); return ( - data.length > 0 && ( + data?.length && + title && ( { const [isFocused, setFocus] = useState(false); @@ -30,7 +29,6 @@ export const Input = ({ ]} onFocus={() => { setFocus(true); - openModal(); }} onBlur={() => setFocus(false)} value={value} diff --git a/src/index.tsx b/src/index.tsx index c379c68..775d252 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -68,11 +68,7 @@ export const DropdownSelect: React.FC = ({ const [listIndex, setListIndex] = useState<{ sectionIndex?: number; itemIndex: number; - }>({ itemIndex: 0 }); // for scrollToIndex in Sectionlist and Flatlist - - if (!options || options.length === 0) { - throw new Error('Options array cannot be empty or undefined'); - } + }>({ itemIndex: 0, sectionIndex: 0 }); // for scrollToIndex in Sectionlist and Flatlist useEffect(() => { setNewOptions(options); @@ -92,7 +88,7 @@ export const DropdownSelect: React.FC = ({ *==========================================*/ // check the structure of the new options array to determine if it is a section list or a - const isSectionList = newOptions.some( + const isSectionList = newOptions?.some( (item) => item.title && item.data && Array.isArray(item.data) ); @@ -102,17 +98,17 @@ export const DropdownSelect: React.FC = ({ const modifiedSectionData = extractPropertyFromArray( newOptions, 'data' - ).flat(); + )?.flat(); /** - *`modifiedOptions` should only be used for computations newOptions remains the default array. - * At this point modifiedOptions now has the same structure for both `FlatList` and `SectionList` + * `options` is the original array, it never changes. (Do not use except you really need the original array) . + * `newOptions` is a copy of options but can be mutated by `setNewOptions`, as a result, the value many change. + * `modifiedOptions` should only be used for computations. It has the same structure for both `FlatList` and `SectionList` */ const modifiedOptions = isSectionList ? modifiedSectionData : newOptions; const optLabel = optionLabel || DEFAULT_OPTION_LABEL; const optValue = optionValue || DEFAULT_OPTION_VALUE; - const optionsCopy = JSON.parse(JSON.stringify(options)); // copy of the original options array /*=========================================== * Selection handlers @@ -143,7 +139,7 @@ export const DropdownSelect: React.FC = ({ }; const removeDisabledItems = (items: TFlatList) => { - return items.filter((item: TFlatListItem) => !item.disabled); + return items?.filter((item: TFlatListItem) => !item.disabled); }; const handleSelectAll = () => { @@ -153,8 +149,8 @@ export const DropdownSelect: React.FC = ({ // don't select disabled items const filteredOptions = removeDisabledItems( isSectionList - ? extractPropertyFromArray(optionsCopy, 'data').flat() - : optionsCopy + ? extractPropertyFromArray(options, 'data').flat() + : options ); if (!prevVal) { @@ -184,7 +180,7 @@ export const DropdownSelect: React.FC = ({ (selectedValues: any[]) => { //if the list contains disabled values, those values will not be selected if ( - removeDisabledItems(modifiedOptions).length === selectedValues.length + removeDisabledItems(modifiedOptions)?.length === selectedValues?.length ) { setSelectAll(true); } else { @@ -234,10 +230,10 @@ export const DropdownSelect: React.FC = ({ const regexFilter = new RegExp(searchText, 'i'); - // Because the options array will be mutated after Search, we have to search with a copy of the original array + // Because the options array will be mutated while searching, we have to search with the original array const searchResults = isSectionList - ? searchSectionList(optionsCopy as TSectionList, regexFilter) - : searchFlatList(optionsCopy as TFlatList, regexFilter); + ? searchSectionList(options as TSectionList, regexFilter) + : searchFlatList(options as TFlatList, regexFilter); setNewOptions(searchResults); }; @@ -300,18 +296,22 @@ export const DropdownSelect: React.FC = ({ *==========================================*/ const setIndexOfSelectedItem = (selectedLabel: string) => { isSectionList - ? optionsCopy.map((item: TSectionListItem, sectionIndex: number) => { - item.data?.find((dataItem: TFlatListItem, itemIndex: number) => { - if (dataItem[optLabel] === selectedLabel) { - setListIndex({ sectionIndex, itemIndex }); + ? (options as TSectionListItem[] | undefined)?.map( + (item: TSectionListItem, sectionIndex: number) => { + item?.data?.find((dataItem: TFlatListItem, itemIndex: number) => { + if (dataItem[optLabel] === selectedLabel) { + setListIndex({ sectionIndex, itemIndex }); + } + }); + } + ) + : (options as TFlatListItem[] | undefined)?.find( + (item: TFlatListItem, itemIndex: number) => { + if (item[optLabel] === selectedLabel) { + setListIndex({ itemIndex }); } - }); - }) - : optionsCopy?.find((item: TFlatListItem, itemIndex: number) => { - if (item[optLabel] === selectedLabel) { - setListIndex({ itemIndex }); } - }); + ); }; return ( @@ -350,7 +350,6 @@ export const DropdownSelect: React.FC = ({ modalProps={modalProps} > {isSearchable && ( @@ -362,12 +361,14 @@ export const DropdownSelect: React.FC = ({ textInputContainerStyle={ searchControls?.textInputContainerStyle } - openModal={() => setOpen(true)} // There seems to a known issue on expo web that closes the modal when the input is focused + placeholder={ + searchControls?.textInputProps?.placeholder || 'Search' + } {...searchControls?.textInputProps} /> )} {listHeaderComponent} - {isMultiple && modifiedOptions.length > 1 && ( + {isMultiple && modifiedOptions?.length > 1 && ( {}}> { - let extractedValue = arr.map((item: any) => item[property]); + let extractedValue = arr?.map((item: any) => item[property]); return extractedValue; };