mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): regional prompting layout, styling
This commit is contained in:
parent
e7523bd1d9
commit
c1aae0815d
@ -1,19 +0,0 @@
|
|||||||
import type { FlexProps } from '@invoke-ai/ui-library';
|
|
||||||
import { Flex, forwardRef } from '@invoke-ai/ui-library';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
import type { RgbaColor, RgbColor } from 'react-colorful';
|
|
||||||
|
|
||||||
type Props = FlexProps & {
|
|
||||||
previewColor: RgbColor | RgbaColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ColorPreview = forwardRef((props: Props, ref) => {
|
|
||||||
const { previewColor, ...rest } = props;
|
|
||||||
const colorString = useMemo(() => {
|
|
||||||
if ('a' in previewColor) {
|
|
||||||
return `rgba(${previewColor.r}, ${previewColor.g}, ${previewColor.b}, ${previewColor.a ?? 1})`;
|
|
||||||
}
|
|
||||||
return `rgba(${previewColor.r}, ${previewColor.g}, ${previewColor.b}, 1)`;
|
|
||||||
}, [previewColor]);
|
|
||||||
return <Flex ref={ref} w="full" h="full" borderRadius="base" backgroundColor={colorString} {...rest} />;
|
|
||||||
});
|
|
@ -1,11 +1,11 @@
|
|||||||
import { Popover, PopoverBody, PopoverContent, PopoverTrigger } from '@invoke-ai/ui-library';
|
import { IconButton, Popover, PopoverBody, PopoverContent, PopoverTrigger } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { ColorPreview } from 'common/components/ColorPreview';
|
|
||||||
import RgbColorPicker from 'common/components/RgbColorPicker';
|
import RgbColorPicker from 'common/components/RgbColorPicker';
|
||||||
import { useLayer } from 'features/regionalPrompts/hooks/layerStateHooks';
|
import { useLayer } from 'features/regionalPrompts/hooks/layerStateHooks';
|
||||||
import { promptRegionLayerColorChanged } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
import { promptRegionLayerColorChanged } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import type { RgbColor } from 'react-colorful';
|
import type { RgbColor } from 'react-colorful';
|
||||||
|
import { PiEyedropperBold } from 'react-icons/pi';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string;
|
id: string;
|
||||||
@ -23,7 +23,7 @@ export const LayerColorPicker = ({ id }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Popover isLazy>
|
<Popover isLazy>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<ColorPreview previewColor={layer.color} />
|
<IconButton aria-label="color picker" size="sm" borderRadius="base" icon={<PiEyedropperBold />} />
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent>
|
||||||
<PopoverBody minH={64}>
|
<PopoverBody minH={64}>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { Flex } from '@invoke-ai/ui-library';
|
import { Flex, Spacer } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { rgbColorToString } from 'features/canvas/util/colorToString';
|
||||||
import { LayerColorPicker } from 'features/regionalPrompts/components/LayerColorPicker';
|
import { LayerColorPicker } from 'features/regionalPrompts/components/LayerColorPicker';
|
||||||
import { LayerMenu } from 'features/regionalPrompts/components/LayerMenu';
|
import { LayerMenu } from 'features/regionalPrompts/components/LayerMenu';
|
||||||
import { LayerVisibilityToggle } from 'features/regionalPrompts/components/LayerVisibilityToggle';
|
import { LayerVisibilityToggle } from 'features/regionalPrompts/components/LayerVisibilityToggle';
|
||||||
import { RegionalPromptsPrompt } from 'features/regionalPrompts/components/RegionalPromptsPrompt';
|
import { RegionalPromptsPrompt } from 'features/regionalPrompts/components/RegionalPromptsPrompt';
|
||||||
import { layerSelected } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
import { layerSelected } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string;
|
id: string;
|
||||||
@ -13,19 +14,24 @@ type Props = {
|
|||||||
|
|
||||||
export const LayerListItem = ({ id }: Props) => {
|
export const LayerListItem = ({ id }: Props) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const selectedLayer = useAppSelector((s) => s.regionalPrompts.selectedLayer);
|
const color = useAppSelector((s) => {
|
||||||
const bg = useMemo(() => (selectedLayer === id ? 'invokeBlue.500' : 'transparent'), [selectedLayer, id]);
|
const color = s.regionalPrompts.layers.find((l) => l.id === id)?.color;
|
||||||
|
if (color) {
|
||||||
|
return rgbColorToString(color);
|
||||||
|
}
|
||||||
|
return 'base.700';
|
||||||
|
});
|
||||||
const onClickCapture = useCallback(() => {
|
const onClickCapture = useCallback(() => {
|
||||||
// Must be capture so that the layer is selected before deleting/resetting/etc
|
// Must be capture so that the layer is selected before deleting/resetting/etc
|
||||||
dispatch(layerSelected(id));
|
dispatch(layerSelected(id));
|
||||||
}, [dispatch, id]);
|
}, [dispatch, id]);
|
||||||
return (
|
return (
|
||||||
<Flex gap={2} onClickCapture={onClickCapture}>
|
<Flex gap={2} onClickCapture={onClickCapture} bg={color} borderRadius="base" p="1px" ps={2}>
|
||||||
<Flex w={2} borderRadius="base" bg={bg} flexShrink={0} py={4} />
|
<Flex flexDir="column" gap={2} w="full" bg="base.850" borderRadius="base" p={2}>
|
||||||
<Flex flexDir="column" gap={2}>
|
|
||||||
<Flex gap={2}>
|
<Flex gap={2}>
|
||||||
<LayerColorPicker id={id} />
|
<LayerColorPicker id={id} />
|
||||||
<LayerVisibilityToggle id={id} />
|
<LayerVisibilityToggle id={id} />
|
||||||
|
<Spacer />
|
||||||
<LayerMenu id={id} />
|
<LayerMenu id={id} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<RegionalPromptsPrompt layerId={id} />
|
<RegionalPromptsPrompt layerId={id} />
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { Box, Textarea } from '@invoke-ai/ui-library';
|
import { Box, Textarea } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { ShowDynamicPromptsPreviewButton } from 'features/dynamicPrompts/components/ShowDynamicPromptsPreviewButton';
|
|
||||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||||
import { usePrompt } from 'features/prompt/usePrompt';
|
import { usePrompt } from 'features/prompt/usePrompt';
|
||||||
import { useLayerPrompt } from 'features/regionalPrompts/hooks/layerStateHooks';
|
import { useLayerPrompt } from 'features/regionalPrompts/hooks/layerStateHooks';
|
||||||
import { promptChanged } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
import { promptChanged } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import { SDXLConcatButton } from 'features/sdxl/components/SDXLPrompts/SDXLConcatButton';
|
|
||||||
import { memo, useCallback, useRef } from 'react';
|
import { memo, useCallback, useRef } from 'react';
|
||||||
import type { HotkeyCallback } from 'react-hotkeys-hook';
|
import type { HotkeyCallback } from 'react-hotkeys-hook';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
@ -20,7 +18,6 @@ type Props = {
|
|||||||
export const RegionalPromptsPrompt = memo((props: Props) => {
|
export const RegionalPromptsPrompt = memo((props: Props) => {
|
||||||
const prompt = useLayerPrompt(props.layerId);
|
const prompt = useLayerPrompt(props.layerId);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const baseModel = useAppSelector((s) => s.generation.model)?.base;
|
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const _onChange = useCallback(
|
const _onChange = useCallback(
|
||||||
@ -46,7 +43,7 @@ export const RegionalPromptsPrompt = memo((props: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
||||||
<Box pos="relative">
|
<Box pos="relative" w="full">
|
||||||
<Textarea
|
<Textarea
|
||||||
id="prompt"
|
id="prompt"
|
||||||
name="prompt"
|
name="prompt"
|
||||||
@ -62,8 +59,6 @@ export const RegionalPromptsPrompt = memo((props: Props) => {
|
|||||||
/>
|
/>
|
||||||
<PromptOverlayButtonWrapper>
|
<PromptOverlayButtonWrapper>
|
||||||
<AddPromptTriggerButton isOpen={isOpen} onOpen={onOpen} />
|
<AddPromptTriggerButton isOpen={isOpen} onOpen={onOpen} />
|
||||||
{baseModel === 'sdxl' && <SDXLConcatButton />}
|
|
||||||
<ShowDynamicPromptsPreviewButton />
|
|
||||||
</PromptOverlayButtonWrapper>
|
</PromptOverlayButtonWrapper>
|
||||||
</Box>
|
</Box>
|
||||||
</PromptPopover>
|
</PromptPopover>
|
||||||
|
@ -40,7 +40,8 @@ export const RegionalPromptsStage: React.FC = memo(() => {
|
|||||||
}, []);
|
}, []);
|
||||||
const sx = useMemo(
|
const sx = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
border: '1px solid cyan',
|
borderRadius: 'base',
|
||||||
|
borderWidth: 1,
|
||||||
cursor: tool === 'move' ? 'default' : 'none',
|
cursor: tool === 'move' ? 'default' : 'none',
|
||||||
}),
|
}),
|
||||||
[tool]
|
[tool]
|
||||||
|
Loading…
Reference in New Issue
Block a user