Skip to content

Commit 8f2a4d2

Browse files
Feature/debounce search (#154)
* Add Search debounce feature * Add default values for debounce * Enable debounce by default and change debounce duration to 300 * Removed debounceSearch references Co-authored-by: Harsh Zalavadiya <[email protected]>
1 parent cafdcd1 commit 8f2a4d2

File tree

5 files changed

+29
-4
lines changed

5 files changed

+29
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export default Example;
8181
| `valueRenderer` | custom dropdown header [docs](#-custom-value-renderer) | `function` | |
8282
| `ItemRenderer` | custom dropdown option [docs](#-custom-item-renderer) | `function` | |
8383
| `ClearIcon` | Custom Clear Icon for Search | `string|function` | |
84+
| `debounceDuration` | debounce duraion for Search | `number` | `300` |
8485
| `ClearSelectedIcon` | Custom Clear Icon for Selected Items | `string|function` | |
8586

8687
## 🔍 Custom filter logic

src/lib/debounce.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const debounce = (func, wait) => {
2+
let timeout;
3+
return function (...args) {
4+
clearTimeout(timeout);
5+
timeout = setTimeout(() => {
6+
func.apply(null, args);
7+
}, wait);
8+
};
9+
};

src/lib/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@ export interface ISelectProps {
3535
className?: string;
3636
onMenuToggle?;
3737
ClearIcon?: string | Function;
38+
debounceDuration?: number;
3839
ClearSelectedIcon?: string | Function;
3940
}

src/multi-select/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const MultiSelect = ({
4646
labelledBy,
4747
onMenuToggle,
4848
ClearIcon,
49+
debounceDuration = 300,
4950
ClearSelectedIcon,
5051
}: ISelectProps) => {
5152
const nvalue = value || [];
@@ -68,6 +69,7 @@ const MultiSelect = ({
6869
filterOptions,
6970
overrideStrings,
7071
ClearIcon,
72+
debounceDuration,
7173
}}
7274
disabled={disabled}
7375
labelledBy={labelledBy}

src/select-panel/index.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
* Select-all item, and the list of options.
55
*/
66
import { css } from "goober";
7-
import React, { useMemo, useState } from "react";
7+
import React, { useCallback, useEffect, useMemo, useState } from "react";
88

99
import { filterOptions } from "../lib/fuzzy-match-utils";
10+
import { debounce } from "../lib/debounce";
1011
import getString from "../lib/get-string";
1112
import { Option } from "../lib/interfaces";
1213
import Cross from "./cross";
@@ -26,6 +27,7 @@ interface ISelectPanelProps {
2627
filterOptions?: (options: Option[], filter: string) => Option[];
2728
overrideStrings?: { [key: string]: string };
2829
ClearIcon?;
30+
debounceDuration?: number;
2931
}
3032

3133
enum FocusType {
@@ -74,11 +76,17 @@ export const SelectPanel = (props: ISelectPanelProps) => {
7476
hasSelectAll,
7577
overrideStrings,
7678
ClearIcon,
79+
debounceDuration,
7780
} = props;
7881
const [searchText, setSearchText] = useState("");
82+
const [searchTextForFilter, setSearchTextForFilter] = useState("");
7983
const [focusIndex, setFocusIndex] = useState(
8084
focusSearchOnOpen && !disableSearch ? FocusType.SEARCH : FocusType.NONE
8185
);
86+
const debouncedSearch = useCallback(
87+
debounce((query) => setSearchTextForFilter(query), debounceDuration),
88+
[]
89+
);
8290

8391
const selectAllOption = {
8492
label: selectAllLabel || getString("selectAll", overrideStrings),
@@ -106,11 +114,15 @@ export const SelectPanel = (props: ISelectPanelProps) => {
106114
};
107115

108116
const handleSearchChange = (e) => {
117+
debouncedSearch(e.target.value);
109118
setSearchText(e.target.value);
110119
setFocusIndex(FocusType.SEARCH);
111120
};
112121

113-
const handleClear = () => setSearchText("");
122+
const handleClear = () => {
123+
setSearchTextForFilter("");
124+
setSearchText("");
125+
};
114126

115127
const handleItemClicked = (index: number) => setFocusIndex(index);
116128

@@ -141,8 +153,8 @@ export const SelectPanel = (props: ISelectPanelProps) => {
141153

142154
const filteredOptions = () =>
143155
customFilterOptions
144-
? customFilterOptions(options, searchText)
145-
: filterOptions(options, searchText);
156+
? customFilterOptions(options, searchTextForFilter)
157+
: filterOptions(options, searchTextForFilter);
146158

147159
const updateFocus = (offset: number) => {
148160
let newFocus = focusIndex + offset;

0 commit comments

Comments
 (0)