mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): improve ux on TI autcomplete
- cursor reinserts at the end of the trigger - `enter` closes the select - popover styling
This commit is contained in:
parent
2415dc1235
commit
fbd6b25b4d
@ -68,17 +68,26 @@ const ParamEmbeddingPopover = (props: Props) => {
|
||||
return (
|
||||
<Popover
|
||||
initialFocusRef={inputRef}
|
||||
returnFocusOnClose={true}
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
placement="bottom"
|
||||
openDelay={0}
|
||||
closeDelay={0}
|
||||
closeOnBlur={true}
|
||||
returnFocusOnClose={true}
|
||||
>
|
||||
<PopoverTrigger>{children}</PopoverTrigger>
|
||||
<PopoverContent sx={{ p: 0, top: -1, shadow: 'dark-lg' }}>
|
||||
<PopoverContent
|
||||
sx={{
|
||||
p: 0,
|
||||
top: -1,
|
||||
shadow: 'dark-lg',
|
||||
bg: 'accent.300',
|
||||
_dark: { bg: 'accent.400' },
|
||||
}}
|
||||
>
|
||||
<PopoverBody
|
||||
sx={{ p: 1, w: `calc(${PARAMETERS_PANEL_WIDTH} - 2rem )` }}
|
||||
sx={{ p: 0.5, w: `calc(${PARAMETERS_PANEL_WIDTH} - 2rem )` }}
|
||||
>
|
||||
<IAIMantineMultiSelect
|
||||
inputRef={inputRef}
|
||||
|
@ -6,6 +6,7 @@ import AddEmbeddingButton from 'features/embedding/components/AddEmbeddingButton
|
||||
import ParamEmbeddingPopover from 'features/embedding/components/ParamEmbeddingPopover';
|
||||
import { setNegativePrompt } from 'features/parameters/store/generationSlice';
|
||||
import { ChangeEvent, KeyboardEvent, useCallback, useRef } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const ParamNegativeConditioning = () => {
|
||||
@ -32,9 +33,14 @@ const ParamNegativeConditioning = () => {
|
||||
[onOpen]
|
||||
);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
const handleSelectEmbedding = useCallback(
|
||||
(v: string) => {
|
||||
const caret = promptRef.current?.selectionStart;
|
||||
if (!promptRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this is where we insert the TI trigger
|
||||
const caret = promptRef.current.selectionStart;
|
||||
|
||||
if (caret === undefined) {
|
||||
return;
|
||||
@ -47,11 +53,22 @@ const ParamNegativeConditioning = () => {
|
||||
}
|
||||
|
||||
newPrompt += `${v}>`;
|
||||
|
||||
// we insert the cursor after the `>`
|
||||
const finalCaretPos = newPrompt.length;
|
||||
|
||||
newPrompt += negativePrompt.slice(caret);
|
||||
|
||||
dispatch(setNegativePrompt(newPrompt));
|
||||
// must flush dom updates else selection gets reset
|
||||
flushSync(() => {
|
||||
dispatch(setNegativePrompt(newPrompt));
|
||||
});
|
||||
|
||||
// set the caret position to just after the TI trigger promptRef.current.selectionStart = finalCaretPos;
|
||||
promptRef.current.selectionEnd = finalCaretPos;
|
||||
onClose();
|
||||
},
|
||||
[dispatch, negativePrompt]
|
||||
[dispatch, onClose, negativePrompt]
|
||||
);
|
||||
|
||||
return (
|
||||
@ -59,7 +76,7 @@ const ParamNegativeConditioning = () => {
|
||||
<ParamEmbeddingPopover
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onSelect={handleSelect}
|
||||
onSelect={handleSelectEmbedding}
|
||||
>
|
||||
<IAITextarea
|
||||
id="negativePrompt"
|
||||
|
@ -17,6 +17,7 @@ import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke';
|
||||
import AddEmbeddingButton from 'features/embedding/components/AddEmbeddingButton';
|
||||
import ParamEmbeddingPopover from 'features/embedding/components/ParamEmbeddingPopover';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -45,7 +46,6 @@ const ParamPositiveConditioning = () => {
|
||||
const promptRef = useRef<HTMLTextAreaElement>(null);
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChangePrompt = useCallback(
|
||||
(e: ChangeEvent<HTMLTextAreaElement>) => {
|
||||
dispatch(setPositivePrompt(e.target.value));
|
||||
@ -61,6 +61,45 @@ const ParamPositiveConditioning = () => {
|
||||
[]
|
||||
);
|
||||
|
||||
const handleSelectEmbedding = useCallback(
|
||||
(v: string) => {
|
||||
if (!promptRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this is where we insert the TI trigger
|
||||
const caret = promptRef.current.selectionStart;
|
||||
|
||||
if (caret === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newPrompt = prompt.slice(0, caret);
|
||||
|
||||
if (newPrompt[newPrompt.length - 1] !== '<') {
|
||||
newPrompt += '<';
|
||||
}
|
||||
|
||||
newPrompt += `${v}>`;
|
||||
|
||||
// we insert the cursor after the `>`
|
||||
const finalCaretPos = newPrompt.length;
|
||||
|
||||
newPrompt += prompt.slice(caret);
|
||||
|
||||
// must flush dom updates else selection gets reset
|
||||
flushSync(() => {
|
||||
dispatch(setPositivePrompt(newPrompt));
|
||||
});
|
||||
|
||||
// set the caret position to just after the TI trigger
|
||||
promptRef.current.selectionStart = finalCaretPos;
|
||||
promptRef.current.selectionEnd = finalCaretPos;
|
||||
onClose();
|
||||
},
|
||||
[dispatch, onClose, prompt]
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Enter' && e.shiftKey === false && isReady) {
|
||||
@ -75,27 +114,10 @@ const ParamPositiveConditioning = () => {
|
||||
[isReady, dispatch, activeTabName, onOpen]
|
||||
);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(v: string) => {
|
||||
const caret = promptRef.current?.selectionStart;
|
||||
|
||||
if (caret === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newPrompt = prompt.slice(0, caret);
|
||||
|
||||
if (newPrompt[newPrompt.length - 1] !== '<') {
|
||||
newPrompt += '<';
|
||||
}
|
||||
|
||||
newPrompt += `${v}>`;
|
||||
newPrompt += prompt.slice(caret);
|
||||
|
||||
dispatch(setPositivePrompt(newPrompt));
|
||||
},
|
||||
[dispatch, prompt]
|
||||
);
|
||||
// const handleSelect = (e: MouseEvent<HTMLTextAreaElement>) => {
|
||||
// const target = e.target as HTMLTextAreaElement;
|
||||
// setCaret({ start: target.selectionStart, end: target.selectionEnd });
|
||||
// };
|
||||
|
||||
return (
|
||||
<Box>
|
||||
@ -103,7 +125,7 @@ const ParamPositiveConditioning = () => {
|
||||
<ParamEmbeddingPopover
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onSelect={handleSelect}
|
||||
onSelect={handleSelectEmbedding}
|
||||
>
|
||||
<IAITextarea
|
||||
id="prompt"
|
||||
|
Loading…
Reference in New Issue
Block a user