Created
September 23, 2026 16:03
-
-
Save johnloy/29f2970b618b7cce4e73768de98087f4 to your computer and use it in GitHub Desktop.
Ensure at least one option in a multi-select set stays selected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Toggles an option in a multi-select list while guaranteeing at least one | |
| * option stays selected. | |
| * | |
| * Checking adds the option. Unchecking removes it unless it is the last | |
| * remaining selection; in that case the next option in `options` is selected | |
| * instead (wrapping to the start). With two options, unchecking A selects B. | |
| * With one option the same item stays on. | |
| */ | |
| export const toggleSelectionKeepOne = <T>( | |
| selected: readonly T[], | |
| toggled: T, | |
| options: readonly T[], | |
| nextChecked: boolean | |
| ): T[] => { | |
| const selectedSet = new Set(selected); | |
| if (nextChecked) { | |
| return options.filter( | |
| option => option === toggled || selectedSet.has(option) | |
| ); | |
| } | |
| const remaining = selected.filter(option => option !== toggled); | |
| if (remaining.length > 0) { | |
| return remaining; | |
| } | |
| if (options.length === 0) { | |
| return []; | |
| } | |
| const currentIndex = options.indexOf(toggled); | |
| const fallbackIndex = | |
| currentIndex === -1 ? 0 : (currentIndex + 1) % options.length; | |
| return [options[fallbackIndex]]; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment