File size: 2,165 Bytes
8a37e0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { Button, Flex, FormControl, FormLabel, Textarea } from '@invoke-ai/ui-library';
import { PRESET_PLACEHOLDER } from 'features/stylePresets/hooks/usePresetModifiedPrompts';
import type { ChangeEventHandler } from 'react';
import { useCallback, useMemo, useRef } from 'react';
import type { UseControllerProps } from 'react-hook-form';
import { useController } from 'react-hook-form';
import { useTranslation } from 'react-i18next';

import type { StylePresetFormData } from './StylePresetForm';

interface Props extends UseControllerProps<StylePresetFormData, 'negativePrompt' | 'positivePrompt'> {
  label: string;
}

export const StylePresetPromptField = (props: Props) => {
  const { field } = useController(props);
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const { t } = useTranslation();

  const onChange = useCallback<ChangeEventHandler<HTMLTextAreaElement>>(
    (v) => {
      field.onChange(v.target.value);
    },
    [field]
  );

  const value = useMemo(() => {
    return field.value;
  }, [field.value]);

  const insertPromptPlaceholder = useCallback(() => {
    if (textareaRef.current) {
      const cursorPos = textareaRef.current.selectionStart;
      const textBeforeCursor = value.slice(0, cursorPos);
      const textAfterCursor = value.slice(cursorPos);
      const newValue = textBeforeCursor + PRESET_PLACEHOLDER + textAfterCursor;

      field.onChange(newValue);
    } else {
      field.onChange(value + PRESET_PLACEHOLDER);
    }

    textareaRef.current?.focus();
  }, [value, field, textareaRef]);

  const isPromptPresent = useMemo(() => value?.includes(PRESET_PLACEHOLDER), [value]);

  return (
    <FormControl orientation="vertical" gap={3}>
      <Flex alignItems="center" gap={2}>
        <FormLabel>{props.label}</FormLabel>
        <Button
          onClick={insertPromptPlaceholder}
          size="xs"
          aria-label={t('stylePresets.insertPlaceholder')}
          isDisabled={isPromptPresent}
        >
          {t('stylePresets.insertPlaceholder')}
        </Button>
      </Flex>

      <Textarea size="sm" ref={textareaRef} value={value} onChange={onChange} />
    </FormControl>
  );
};