mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): fix selection on dropdowns
Mantine's multiselect does not let you edit the search box with mouse, paste into it, etc. Normal select is fine. I can't remember why I made Lora etc multiselects, but everything seems to work with normal selects, so I've change to that.
This commit is contained in:
parent
81817532f8
commit
be06d4c0af
@ -59,6 +59,7 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
|
||||
onKeyDown={handleKeyDown}
|
||||
onKeyUp={handleKeyUp}
|
||||
searchable={searchable}
|
||||
maxDropdownHeight={300}
|
||||
styles={() => ({
|
||||
label: {
|
||||
color: mode(base700, base300)(colorMode),
|
||||
|
@ -3,7 +3,7 @@ import { Select, SelectProps } from '@mantine/core';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
|
||||
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
|
||||
import { KeyboardEvent, memo, useCallback } from 'react';
|
||||
import { KeyboardEvent, RefObject, memo, useCallback, useState } from 'react';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
export type IAISelectDataType = {
|
||||
@ -14,10 +14,11 @@ export type IAISelectDataType = {
|
||||
|
||||
type IAISelectProps = SelectProps & {
|
||||
tooltip?: string;
|
||||
inputRef?: RefObject<HTMLInputElement>;
|
||||
};
|
||||
|
||||
const IAIMantineSelect = (props: IAISelectProps) => {
|
||||
const { searchable = true, tooltip, ...rest } = props;
|
||||
const { searchable = true, tooltip, inputRef, onChange, ...rest } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
const {
|
||||
base50,
|
||||
@ -38,7 +39,9 @@ const IAIMantineSelect = (props: IAISelectProps) => {
|
||||
} = useChakraThemeTokens();
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
|
||||
// we want to capture shift keypressed even when an input is focused
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.shiftKey) {
|
||||
@ -57,14 +60,33 @@ const IAIMantineSelect = (props: IAISelectProps) => {
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
// wrap onChange to clear search value on select
|
||||
const handleChange = useCallback(
|
||||
(v: string | null) => {
|
||||
setSearchValue('');
|
||||
|
||||
if (!onChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
onChange(v);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const [boxShadow] = useToken('shadows', ['dark-lg']);
|
||||
|
||||
return (
|
||||
<Tooltip label={tooltip} placement="top" hasArrow>
|
||||
<Select
|
||||
ref={inputRef}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={setSearchValue}
|
||||
onChange={handleChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
onKeyUp={handleKeyUp}
|
||||
searchable={searchable}
|
||||
maxDropdownHeight={300}
|
||||
styles={() => ({
|
||||
label: {
|
||||
color: mode(base700, base300)(colorMode),
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
import { SelectItem } from '@mantine/core';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
|
||||
import IAIMantineSelect from 'common/components/IAIMantineSelect';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { MODEL_TYPE_MAP } from 'features/system/components/ModelSelect';
|
||||
import { forEach } from 'lodash-es';
|
||||
@ -61,12 +61,12 @@ const ParamEmbeddingPopover = (props: Props) => {
|
||||
}, [embeddingQueryData, currentMainModel?.base_model]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(v: string[]) => {
|
||||
if (v.length === 0) {
|
||||
(v: string | null) => {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
|
||||
onSelect(v[0]);
|
||||
onSelect(v);
|
||||
},
|
||||
[onSelect]
|
||||
);
|
||||
@ -106,16 +106,16 @@ const ParamEmbeddingPopover = (props: Props) => {
|
||||
</Text>
|
||||
</Flex>
|
||||
) : (
|
||||
<IAIMantineMultiSelect
|
||||
<IAIMantineSelect
|
||||
inputRef={inputRef}
|
||||
autoFocus
|
||||
placeholder={'Add Embedding'}
|
||||
value={[]}
|
||||
value={null}
|
||||
data={data}
|
||||
maxDropdownHeight={400}
|
||||
nothingFound="No Matching Embeddings"
|
||||
nothingFound="No matching Embeddings"
|
||||
itemComponent={IAIMantineSelectItemWithTooltip}
|
||||
disabled={data.length === 0}
|
||||
filter={(value, selected, item: SelectItem) =>
|
||||
filter={(value, item: SelectItem) =>
|
||||
item.label
|
||||
?.toLowerCase()
|
||||
.includes(value.toLowerCase().trim()) ||
|
||||
|
@ -4,7 +4,7 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { RootState, stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
|
||||
import IAIMantineSelect from 'common/components/IAIMantineSelect';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { loraAdded } from 'features/lora/store/loraSlice';
|
||||
import { MODEL_TYPE_MAP } from 'features/system/components/ModelSelect';
|
||||
@ -58,12 +58,15 @@ const ParamLoraSelect = () => {
|
||||
}, [loras, lorasQueryData, currentMainModel?.base_model]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(v: string[]) => {
|
||||
const loraEntity = lorasQueryData?.entities[v[0]];
|
||||
(v: string | null | undefined) => {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
const loraEntity = lorasQueryData?.entities[v];
|
||||
if (!loraEntity) {
|
||||
return;
|
||||
}
|
||||
v[0] && dispatch(loraAdded(loraEntity));
|
||||
dispatch(loraAdded(loraEntity));
|
||||
},
|
||||
[dispatch, lorasQueryData?.entities]
|
||||
);
|
||||
@ -79,15 +82,14 @@ const ParamLoraSelect = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<IAIMantineMultiSelect
|
||||
<IAIMantineSelect
|
||||
placeholder={data.length === 0 ? 'All LoRAs added' : 'Add LoRA'}
|
||||
value={[]}
|
||||
value={null}
|
||||
data={data}
|
||||
maxDropdownHeight={400}
|
||||
nothingFound="No matching LoRAs"
|
||||
itemComponent={IAIMantineSelectItemWithTooltip}
|
||||
disabled={data.length === 0}
|
||||
filter={(value, selected, item: SelectItem) =>
|
||||
filter={(value, item: SelectItem) =>
|
||||
item.label?.toLowerCase().includes(value.toLowerCase().trim()) ||
|
||||
item.value.toLowerCase().includes(value.toLowerCase().trim())
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
import 'reactflow/dist/style.css';
|
||||
import { useCallback, forwardRef } from 'react';
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { nodeAdded, nodesSelector } from '../store/nodesSlice';
|
||||
import { map } from 'lodash-es';
|
||||
import { useBuildInvocation } from '../hooks/useBuildInvocation';
|
||||
import { AnyInvocationType } from 'services/events/types';
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect';
|
||||
import IAIMantineSelect from 'common/components/IAIMantineSelect';
|
||||
import { map } from 'lodash-es';
|
||||
import { forwardRef, useCallback } from 'react';
|
||||
import 'reactflow/dist/style.css';
|
||||
import { AnyInvocationType } from 'services/events/types';
|
||||
import { useBuildInvocation } from '../hooks/useBuildInvocation';
|
||||
import { nodeAdded, nodesSelector } from '../store/nodesSlice';
|
||||
|
||||
type NodeTemplate = {
|
||||
label: string;
|
||||
@ -58,24 +58,33 @@ const AddNodeMenu = () => {
|
||||
[dispatch, buildInvocation, toaster]
|
||||
);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(v: string | null) => {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
|
||||
addNode(v as AnyInvocationType);
|
||||
},
|
||||
[addNode]
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex sx={{ gap: 2, alignItems: 'center' }}>
|
||||
<IAIMantineMultiSelect
|
||||
<IAIMantineSelect
|
||||
selectOnBlur={false}
|
||||
placeholder="Add Node"
|
||||
value={[]}
|
||||
value={null}
|
||||
data={data}
|
||||
maxDropdownHeight={400}
|
||||
nothingFound="No matching nodes"
|
||||
itemComponent={SelectItem}
|
||||
filter={(value, selected, item: NodeTemplate) =>
|
||||
filter={(value, item: NodeTemplate) =>
|
||||
item.label.toLowerCase().includes(value.toLowerCase().trim()) ||
|
||||
item.value.toLowerCase().includes(value.toLowerCase().trim()) ||
|
||||
item.description.toLowerCase().includes(value.toLowerCase().trim())
|
||||
}
|
||||
onChange={(v) => {
|
||||
v[0] && addNode(v[0] as AnyInvocationType);
|
||||
}}
|
||||
onChange={handleChange}
|
||||
sx={{
|
||||
width: '18rem',
|
||||
}}
|
||||
|
Loading…
Reference in New Issue
Block a user