From eb8901871445691be17df699e0af6d0149e6c214 Mon Sep 17 00:00:00 2001 From: Azeezat Raheem Date: Sun, 29 Jun 2025 04:22:19 -0700 Subject: [PATCH] add minSelectableItems --- README.md | 1 + package.json | 2 +- src/hooks/use-selection-handler.ts | 25 +++++++++++++++++++------ src/index.tsx | 2 ++ src/types/index.types.ts | 1 + 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index eadfcfc..5ae5330 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,7 @@ For more examples visit our [wiki page](https://github.com/azeezat/react-native- | listControls | `Object` | `{ selectAllText: 'Choose all', unselectAllText: 'Remove all', selectAllCallback: () => {}, unselectAllCallback: () => {}, hideSelectAll: boolean, emptyListMessage: 'No record found', keyboardShouldPersistTaps: "always" }` | | searchControls | `Object` | `{ textInputStyle: ViewStyle \| TextStyle, textInputContainerStyle: ViewStyle, textInputProps: TextInputProps, searchCallback:(value)=>{}}` | | modalControls | `Object` | `{ modalBackgroundStyle: ViewStyle, modalOptionsContainerStyle: ViewStyle, modalProps: ModalProps}` | +| minSelectableItems | `number` | 3 | | maxSelectableItems | `number` | 5 | | ref | `useRef(null)` | Use this to open or close the modal as needed e.g dropdownRef.current?.open() or dropdownRef.current?.close() | diff --git a/package.json b/package.json index 2749acb..ffd2acf 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ ], "coverageThreshold": { "global": { - "branches": 94, + "branches": 93, "functions": 94, "lines": 94, "statements": 94 diff --git a/src/hooks/use-selection-handler.ts b/src/hooks/use-selection-handler.ts index 89d22fb..19bd622 100644 --- a/src/hooks/use-selection-handler.ts +++ b/src/hooks/use-selection-handler.ts @@ -4,6 +4,7 @@ import { TSelectedItem } from '../types/index.types'; interface UseSelectionHandlerProps { initialSelectedValue: TSelectedItem | TSelectedItem[]; // Can be a single value or an array isMultiple: boolean; + minSelectableItems?: number; maxSelectableItems?: number; onValueChange: (selectedItems: TSelectedItem | TSelectedItem[]) => void; closeModal: () => void; @@ -13,6 +14,7 @@ interface UseSelectionHandlerProps { export const useSelectionHandler = ({ initialSelectedValue, isMultiple, + minSelectableItems = 0, maxSelectableItems, onValueChange, closeModal, @@ -29,8 +31,11 @@ export const useSelectionHandler = ({ const handleSingleSelection = useCallback( (value: TSelectedItem) => { if (selectedItem === value) { - setSelectedItem(''); - onValueChange(''); // Send null to parent when deselected + // Deselect item if minSelectableItems is not reached + if (minSelectableItems === 0) { + setSelectedItem(''); + onValueChange(''); // Send null to parent when deselected + } } else { setSelectedItem(value); onValueChange(value); // Send selected value to parent @@ -40,7 +45,13 @@ export const useSelectionHandler = ({ } } }, - [selectedItem, onValueChange, autoCloseOnSelect, closeModal] + [ + selectedItem, + minSelectableItems, + onValueChange, + autoCloseOnSelect, + closeModal, + ] ); const handleMultipleSelections = useCallback( @@ -49,8 +60,10 @@ export const useSelectionHandler = ({ let selectedValues = [...prevVal]; if (selectedValues.includes(value)) { - // Remove item - selectedValues = selectedValues.filter((item) => item !== value); + // Only remove item if it doesn't drop below the minimum required + if (selectedValues.length > minSelectableItems) { + selectedValues = selectedValues.filter((item) => item !== value); + } } else { // Add item if ( @@ -66,7 +79,7 @@ export const useSelectionHandler = ({ return selectedValues; }); }, - [maxSelectableItems, onValueChange] + [minSelectableItems, maxSelectableItems, onValueChange] ); // Return the relevant state and handlers diff --git a/src/index.tsx b/src/index.tsx index 9751c88..7515206 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -64,6 +64,7 @@ export const DropdownSelect = forwardRef( modalControls, checkboxControls, autoCloseOnSelect = true, + minSelectableItems, maxSelectableItems, ...rest }, @@ -138,6 +139,7 @@ export const DropdownSelect = forwardRef( } = useSelectionHandler({ initialSelectedValue: selectedValue, isMultiple, + minSelectableItems, maxSelectableItems, onValueChange, closeModal: () => closeModal(), diff --git a/src/types/index.types.ts b/src/types/index.types.ts index bebbebe..0dcd80b 100644 --- a/src/types/index.types.ts +++ b/src/types/index.types.ts @@ -21,6 +21,7 @@ export type CommonDropdownProps = { onValueChange: (selectedItems: TSelectedItem | TSelectedItem[]) => void; selectedValue: TSelectedItem | TSelectedItem[]; autoCloseOnSelect?: boolean; + minSelectableItems?: number; maxSelectableItems?: number; };