mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Limiting how many options are shown in select dropdowns (#3062)
Introducing a limit to how many options are shown in select dropdowns. Fixes an issue I was experiencing where large numbers of options (5000 tags) was causing dropdown to be unresponsive. Does not effect filtering, always shows 'Create "..."' option if it exists, and shows a notice at the bottom of the dropdown of how many options were hidden from the list if any were.
This commit is contained in:
committed by
GitHub
parent
d2743cf5fb
commit
404a68c994
@@ -6,6 +6,8 @@ import Select, {
|
|||||||
components as reactSelectComponents,
|
components as reactSelectComponents,
|
||||||
GroupedOptionsType,
|
GroupedOptionsType,
|
||||||
OptionsType,
|
OptionsType,
|
||||||
|
MenuListComponentProps,
|
||||||
|
GroupTypeBase,
|
||||||
} from "react-select";
|
} from "react-select";
|
||||||
import CreatableSelect from "react-select/creatable";
|
import CreatableSelect from "react-select/creatable";
|
||||||
import debounce from "lodash-es/debounce";
|
import debounce from "lodash-es/debounce";
|
||||||
@@ -116,6 +118,55 @@ const getSelectedItems = (selectedItems: ValueType<Option, boolean>) =>
|
|||||||
const getSelectedValues = (selectedItems: ValueType<Option, boolean>) =>
|
const getSelectedValues = (selectedItems: ValueType<Option, boolean>) =>
|
||||||
getSelectedItems(selectedItems).map((item) => item.value);
|
getSelectedItems(selectedItems).map((item) => item.value);
|
||||||
|
|
||||||
|
const LimitedSelectMenu = <T extends boolean>(
|
||||||
|
props: MenuListComponentProps<Option, T, GroupTypeBase<Option>>
|
||||||
|
) => {
|
||||||
|
const maxOptionsShown = 200;
|
||||||
|
const [hiddenCount, setHiddenCount] = useState<number>(0);
|
||||||
|
const hiddenCountStyle = {
|
||||||
|
padding: "8px 12px",
|
||||||
|
opacity: "50%",
|
||||||
|
};
|
||||||
|
const menuChildren = useMemo(() => {
|
||||||
|
if (Array.isArray(props.children)) {
|
||||||
|
// limit the number of select options showing in the select dropdowns
|
||||||
|
// always showing the 'Create "..."' option when it exists
|
||||||
|
let creationOptionIndex = (props.children as React.ReactNodeArray).findIndex(
|
||||||
|
(child: React.ReactNode) => {
|
||||||
|
let maybeCreatableOption = child as React.ReactElement<
|
||||||
|
OptionProps<
|
||||||
|
Option & { __isNew__: boolean },
|
||||||
|
T,
|
||||||
|
GroupTypeBase<Option & { __isNew__: boolean }>
|
||||||
|
>,
|
||||||
|
""
|
||||||
|
>;
|
||||||
|
return maybeCreatableOption?.props?.data?.__isNew__;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (creationOptionIndex >= maxOptionsShown) {
|
||||||
|
setHiddenCount(props.children.length - maxOptionsShown - 1);
|
||||||
|
return props.children
|
||||||
|
.slice(0, maxOptionsShown - 1)
|
||||||
|
.concat([props.children[creationOptionIndex]]);
|
||||||
|
} else {
|
||||||
|
setHiddenCount(Math.max(props.children.length - maxOptionsShown, 0));
|
||||||
|
return props.children.slice(0, maxOptionsShown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setHiddenCount(0);
|
||||||
|
return props.children;
|
||||||
|
}, [props.children]);
|
||||||
|
return (
|
||||||
|
<reactSelectComponents.MenuList {...props}>
|
||||||
|
{menuChildren}
|
||||||
|
{hiddenCount > 0 && (
|
||||||
|
<div style={hiddenCountStyle}>{hiddenCount} Options Hidden</div>
|
||||||
|
)}
|
||||||
|
</reactSelectComponents.MenuList>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const SelectComponent = <T extends boolean>({
|
const SelectComponent = <T extends boolean>({
|
||||||
type,
|
type,
|
||||||
initialIds,
|
initialIds,
|
||||||
@@ -191,6 +242,7 @@ const SelectComponent = <T extends boolean>({
|
|||||||
menuPortalTarget,
|
menuPortalTarget,
|
||||||
components: {
|
components: {
|
||||||
...components,
|
...components,
|
||||||
|
MenuList: LimitedSelectMenu,
|
||||||
IndicatorSeparator: () => null,
|
IndicatorSeparator: () => null,
|
||||||
...((!showDropdown || isDisabled) && { DropdownIndicator: () => null }),
|
...((!showDropdown || isDisabled) && { DropdownIndicator: () => null }),
|
||||||
...(isDisabled && { MultiValueRemove: () => null }),
|
...(isDisabled && { MultiValueRemove: () => null }),
|
||||||
|
|||||||
Reference in New Issue
Block a user