Skip to content

Commit

Permalink
async filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
amcdnl committed Jul 17, 2024
1 parent 7d3b6ab commit 66fc83d
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 13 deletions.
23 changes: 14 additions & 9 deletions src/form/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export interface SelectProps {
/**
* Whether you can filter the select options.
*/
filterable?: boolean;
filterable?: boolean | 'async';

/**
* Whether you can clear the select after selection.
Expand Down Expand Up @@ -287,14 +287,19 @@ export const Select: FC<SelectProps> = ({
}
}, [children, options]);

const { result, keyword, search, resetSearch } = useFuzzy<SelectOptionProps>(
options,
{
keys: ['children', 'group'],
...searchOptions,
getFn: menuDisabled ? () => '' : searchOptions?.getFn
}
);
const {
result: fuseResult,
keyword,
search,
resetSearch
} = useFuzzy<SelectOptionProps>(options, {
keys: ['children', 'group'],
...searchOptions,
getFn: menuDisabled ? () => '' : searchOptions?.getFn
});

// TODO: Come back and cleanup the fuzzy search to be more extensible
const result = filterable === 'async' ? options : fuseResult;

// If a keyword is used to filter options, automatically
// highlight the first option for easy selection
Expand Down
2 changes: 1 addition & 1 deletion src/form/Select/SelectInput/SelectInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export interface SelectInputProps {
/**
* If true, the select input is filterable.
*/
filterable?: boolean;
filterable?: boolean | 'async';

/**
* If true, the select input allows multiple selection.
Expand Down
6 changes: 3 additions & 3 deletions src/form/Select/SelectMenu/SelectMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export interface SelectMenuProps {
/**
* Whether users can filter the options or not.
*/
filterable?: boolean;
filterable?: boolean | 'async';

/**
* Whether the component is loading or not.
Expand Down Expand Up @@ -226,7 +226,7 @@ export const SelectMenu: FC<SelectMenuProps> = ({
)}
{options?.length === 0 &&
!createable &&
filterable &&
filterable === true &&
trimmedText &&
!loading && (
<ListItem className="select-menu-empty-search">
Expand All @@ -235,7 +235,7 @@ export const SelectMenu: FC<SelectMenuProps> = ({
)}
{options?.length === 0 &&
!createable &&
filterable &&
filterable === true &&
!trimmedText &&
!loading && (
<ListItem className="select-menu-empty">
Expand Down
55 changes: 55 additions & 0 deletions src/form/Select/SingleSelect.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,61 @@ export const AsyncDefaultValue = () => {
);
};

export const AsyncFiltering = () => {
const [inputValue, setInputValue] = useState<string | null>(null);
const [value, setValue] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const [opts, setOpts] = useState<{ value: string; label: string }[] | null>(
null
);

useEffect(() => {
let timeout;

async function getOptions() {
const next = await new Promise<any>(resolve => {
timeout = setTimeout(() => {
resolve(options);
}, 300);
});

const filtered = next.filter(n => n.label.includes(inputValue));
setOpts(filtered);
setLoading(false);
}

if (inputValue) {
getOptions();
} else {
setOpts(null);
setLoading(false);
}

return () => {
clearTimeout(timeout);
};
}, [inputValue]);

return (
<div style={{ width: 300 }}>
<Select
placeholder="Start typing to find options..."
filterable="async"
loading={loading}
value={value}
onChange={v => setValue(v)}
onInputKeydown={(e: any) => setInputValue(e.target.value)}
>
{opts?.map(o => (
<SelectOption key={o.value} value={o.value}>
{o.label}
</SelectOption>
))}
</Select>
</div>
);
};

export const CustomLabels = () => {
const [value, setValue] = useState<string | null>('facebook');
return (
Expand Down

0 comments on commit 66fc83d

Please sign in to comment.