| 23 | }; |
| 24 | |
| 25 | export function SortPicker({ |
| 26 | onChange, |
| 27 | value, |
| 28 | placeholder, |
| 29 | filter, |
| 30 | getSortOptions, |
| 31 | isClearable, |
| 32 | disabled, |
| 33 | width, |
| 34 | }: Props) { |
| 35 | // Using sync Select and manual options fetching here since we need to find the selected option by value |
| 36 | const options = useAsync<() => Promise<SelectableValue[]>>(async () => { |
| 37 | const vals = await (getSortOptions ?? defaultSortOptionsGetter)(); |
| 38 | if (filter) { |
| 39 | return vals.filter((v) => filter.includes(v.value)); |
| 40 | } |
| 41 | return vals; |
| 42 | }, [getSortOptions, filter]); |
| 43 | |
| 44 | if (options.loading) { |
| 45 | return null; |
| 46 | } |
| 47 | |
| 48 | const isDesc = Boolean(value?.includes('desc') || value?.startsWith('-')); // bluge syntax starts with "-" |
| 49 | return ( |
| 50 | <Select |
| 51 | key={value} |
| 52 | width={width} |
| 53 | onChange={onChange} |
| 54 | value={options.value?.find((opt) => opt.value === value) ?? null} |
| 55 | options={options.value} |
| 56 | aria-label={t('sort-picker.select-aria-label', 'Sort')} |
| 57 | placeholder={placeholder ?? `Sort (Default ${DEFAULT_SORT.label})`} |
| 58 | prefix={<Icon name={isDesc ? 'sort-amount-down' : 'sort-amount-up'} />} |
| 59 | isClearable={isClearable} |
| 60 | disabled={disabled} |
| 61 | /> |
| 62 | ); |
| 63 | } |