Add asyncValues and asyncDebounce to props and implement in select filter.
Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
@@ -56,3 +56,19 @@ export const SelectFilter = () => {
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
export const AsyncSelectFilter = () => {
|
||||
return (
|
||||
<Paper style={{ padding: 10 }}>
|
||||
<SearchFilter.Select
|
||||
name="Asynchronous Values"
|
||||
asyncValues={async () => {
|
||||
const response = await fetch('https://swapi.dev/api/planets');
|
||||
const json: { results: Array<{ name: string }> } =
|
||||
await response.json();
|
||||
return json.results.map(r => r.name);
|
||||
}}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
} from '@material-ui/core';
|
||||
|
||||
import { useSearch } from '../SearchContext';
|
||||
import { useAsyncFilterValues } from './hooks';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
label: {
|
||||
@@ -34,24 +35,29 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
export type Component = {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type SearchFilterComponentProps = {
|
||||
className?: string;
|
||||
name: string;
|
||||
label?: string;
|
||||
values?: string[];
|
||||
asyncValues?: (partial: string) => Promise<string[]>;
|
||||
asyncDebounce?: number;
|
||||
defaultValue?: string[] | string | null;
|
||||
};
|
||||
|
||||
export type Props = Component & {
|
||||
component: (props: Component) => ReactElement;
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type SearchFilterWrapperProps = SearchFilterComponentProps & {
|
||||
component: (props: SearchFilterComponentProps) => ReactElement;
|
||||
debug?: boolean;
|
||||
};
|
||||
|
||||
const CheckboxFilter = ({
|
||||
className,
|
||||
name,
|
||||
defaultValue,
|
||||
values = [],
|
||||
}: Component) => {
|
||||
const CheckboxFilter = (props: SearchFilterComponentProps) => {
|
||||
const { className, defaultValue, label, name, values = [] } = props;
|
||||
const classes = useStyles();
|
||||
const { filters, setFilters } = useSearch();
|
||||
|
||||
@@ -84,7 +90,7 @@ const CheckboxFilter = ({
|
||||
fullWidth
|
||||
data-testid="search-checkboxfilter-next"
|
||||
>
|
||||
<FormLabel className={classes.label}>{name}</FormLabel>
|
||||
<FormLabel className={classes.label}>{label || name}</FormLabel>
|
||||
{values.map((value: string) => (
|
||||
<FormControlLabel
|
||||
key={value}
|
||||
@@ -106,13 +112,23 @@ const CheckboxFilter = ({
|
||||
);
|
||||
};
|
||||
|
||||
const SelectFilter = ({
|
||||
className,
|
||||
name,
|
||||
defaultValue,
|
||||
values = [],
|
||||
}: Component) => {
|
||||
const SelectFilter = (props: SearchFilterComponentProps) => {
|
||||
const {
|
||||
asyncValues,
|
||||
asyncDebounce,
|
||||
className,
|
||||
defaultValue,
|
||||
label,
|
||||
name,
|
||||
values: givenValues,
|
||||
} = props;
|
||||
const classes = useStyles();
|
||||
const { value: values = [], loading } = useAsyncFilterValues(
|
||||
asyncValues,
|
||||
'',
|
||||
givenValues,
|
||||
asyncDebounce,
|
||||
);
|
||||
const { filters, setFilters } = useSearch();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -138,13 +154,14 @@ const SelectFilter = ({
|
||||
|
||||
return (
|
||||
<FormControl
|
||||
disabled={loading}
|
||||
className={className}
|
||||
variant="filled"
|
||||
fullWidth
|
||||
data-testid="search-selectfilter-next"
|
||||
>
|
||||
<InputLabel className={classes.label} margin="dense">
|
||||
{name}
|
||||
{label || name}
|
||||
</InputLabel>
|
||||
<Select
|
||||
variant="outlined"
|
||||
@@ -164,17 +181,20 @@ const SelectFilter = ({
|
||||
);
|
||||
};
|
||||
|
||||
const SearchFilter = ({ component: Element, ...props }: Props) => (
|
||||
<Element {...props} />
|
||||
);
|
||||
const SearchFilter = ({
|
||||
component: Element,
|
||||
...props
|
||||
}: SearchFilterWrapperProps) => <Element {...props} />;
|
||||
|
||||
SearchFilter.Checkbox = (props: Omit<Props, 'component'> & Component) => (
|
||||
<SearchFilter {...props} component={CheckboxFilter} />
|
||||
);
|
||||
SearchFilter.Checkbox = (
|
||||
props: Omit<SearchFilterWrapperProps, 'component'> &
|
||||
SearchFilterComponentProps,
|
||||
) => <SearchFilter {...props} component={CheckboxFilter} />;
|
||||
|
||||
SearchFilter.Select = (props: Omit<Props, 'component'> & Component) => (
|
||||
<SearchFilter {...props} component={SelectFilter} />
|
||||
);
|
||||
SearchFilter.Select = (
|
||||
props: Omit<SearchFilterWrapperProps, 'component'> &
|
||||
SearchFilterComponentProps,
|
||||
) => <SearchFilter {...props} component={SelectFilter} />;
|
||||
|
||||
/**
|
||||
* @deprecated This component was used for rapid prototyping of the Backstage
|
||||
|
||||
@@ -15,3 +15,7 @@
|
||||
*/
|
||||
|
||||
export { SearchFilter, SearchFilterNext } from './SearchFilter';
|
||||
export type {
|
||||
SearchFilterComponentProps,
|
||||
SearchFilterWrapperProps,
|
||||
} from './SearchFilter';
|
||||
|
||||
@@ -33,6 +33,10 @@ export type {
|
||||
} from './components/SearchBar';
|
||||
export { SearchContextProvider, useSearch } from './components/SearchContext';
|
||||
export { SearchFilter, SearchFilterNext } from './components/SearchFilter';
|
||||
export type {
|
||||
SearchFilterComponentProps,
|
||||
SearchFilterWrapperProps,
|
||||
} from './components/SearchFilter';
|
||||
export { SearchModal } from './components/SearchModal';
|
||||
export type { SearchModalProps } from './components/SearchModal';
|
||||
export { SearchPage as Router } from './components/SearchPage';
|
||||
|
||||
Reference in New Issue
Block a user