mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): add layerwrapper component
This commit is contained in:
parent
d55ea318ec
commit
d67480d92c
@ -5,6 +5,7 @@ import { LayerDeleteButton } from 'features/controlLayers/components/LayerCommon
|
|||||||
import { LayerMenu } from 'features/controlLayers/components/LayerCommon/LayerMenu';
|
import { LayerMenu } from 'features/controlLayers/components/LayerCommon/LayerMenu';
|
||||||
import { LayerTitle } from 'features/controlLayers/components/LayerCommon/LayerTitle';
|
import { LayerTitle } from 'features/controlLayers/components/LayerCommon/LayerTitle';
|
||||||
import { LayerVisibilityToggle } from 'features/controlLayers/components/LayerCommon/LayerVisibilityToggle';
|
import { LayerVisibilityToggle } from 'features/controlLayers/components/LayerCommon/LayerVisibilityToggle';
|
||||||
|
import { LayerWrapper } from 'features/controlLayers/components/LayerCommon/LayerWrapper';
|
||||||
import { layerSelected, selectCALayerOrThrow } from 'features/controlLayers/store/controlLayersSlice';
|
import { layerSelected, selectCALayerOrThrow } from 'features/controlLayers/store/controlLayersSlice';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
|
|
||||||
@ -17,37 +18,28 @@ type Props = {
|
|||||||
export const CALayer = memo(({ layerId }: Props) => {
|
export const CALayer = memo(({ layerId }: Props) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const isSelected = useAppSelector((s) => selectCALayerOrThrow(s.controlLayers.present, layerId).isSelected);
|
const isSelected = useAppSelector((s) => selectCALayerOrThrow(s.controlLayers.present, layerId).isSelected);
|
||||||
const onClickCapture = useCallback(() => {
|
const onClick = 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(layerId));
|
dispatch(layerSelected(layerId));
|
||||||
}, [dispatch, layerId]);
|
}, [dispatch, layerId]);
|
||||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<LayerWrapper onClick={onClick} borderColor={isSelected ? 'base.400' : 'base.800'}>
|
||||||
gap={2}
|
<Flex gap={3} alignItems="center" p={3} cursor="pointer" onDoubleClick={onToggle}>
|
||||||
onClickCapture={onClickCapture}
|
<LayerVisibilityToggle layerId={layerId} />
|
||||||
bg={isSelected ? 'base.400' : 'base.800'}
|
<LayerTitle type="control_adapter_layer" />
|
||||||
px={2}
|
<Spacer />
|
||||||
borderRadius="base"
|
<CALayerOpacity layerId={layerId} />
|
||||||
py="1px"
|
<LayerMenu layerId={layerId} />
|
||||||
>
|
<LayerDeleteButton layerId={layerId} />
|
||||||
<Flex flexDir="column" w="full" bg="base.850" borderRadius="base">
|
|
||||||
<Flex gap={3} alignItems="center" p={3} cursor="pointer" onDoubleClick={onToggle}>
|
|
||||||
<LayerVisibilityToggle layerId={layerId} />
|
|
||||||
<LayerTitle type="control_adapter_layer" />
|
|
||||||
<Spacer />
|
|
||||||
<CALayerOpacity layerId={layerId} />
|
|
||||||
<LayerMenu layerId={layerId} />
|
|
||||||
<LayerDeleteButton layerId={layerId} />
|
|
||||||
</Flex>
|
|
||||||
{isOpen && (
|
|
||||||
<Flex flexDir="column" gap={3} px={3} pb={3}>
|
|
||||||
<CALayerControlAdapterWrapper layerId={layerId} />
|
|
||||||
</Flex>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
{isOpen && (
|
||||||
|
<Flex flexDir="column" gap={3} px={3} pb={3}>
|
||||||
|
<CALayerControlAdapterWrapper layerId={layerId} />
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</LayerWrapper>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { IPALayerIPAdapterWrapper } from 'features/controlLayers/components/IPAL
|
|||||||
import { LayerDeleteButton } from 'features/controlLayers/components/LayerCommon/LayerDeleteButton';
|
import { LayerDeleteButton } from 'features/controlLayers/components/LayerCommon/LayerDeleteButton';
|
||||||
import { LayerTitle } from 'features/controlLayers/components/LayerCommon/LayerTitle';
|
import { LayerTitle } from 'features/controlLayers/components/LayerCommon/LayerTitle';
|
||||||
import { LayerVisibilityToggle } from 'features/controlLayers/components/LayerCommon/LayerVisibilityToggle';
|
import { LayerVisibilityToggle } from 'features/controlLayers/components/LayerCommon/LayerVisibilityToggle';
|
||||||
|
import { LayerWrapper } from 'features/controlLayers/components/LayerCommon/LayerWrapper';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -12,21 +13,19 @@ type Props = {
|
|||||||
export const IPALayer = memo(({ layerId }: Props) => {
|
export const IPALayer = memo(({ layerId }: Props) => {
|
||||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
||||||
return (
|
return (
|
||||||
<Flex gap={2} bg="base.800" borderRadius="base" p="1px" px={2}>
|
<LayerWrapper borderColor="base.800">
|
||||||
<Flex flexDir="column" w="full" bg="base.850" borderRadius="base">
|
<Flex gap={3} alignItems="center" p={3} cursor="pointer" onDoubleClick={onToggle}>
|
||||||
<Flex gap={3} alignItems="center" p={3} cursor="pointer" onDoubleClick={onToggle}>
|
<LayerVisibilityToggle layerId={layerId} />
|
||||||
<LayerVisibilityToggle layerId={layerId} />
|
<LayerTitle type="ip_adapter_layer" />
|
||||||
<LayerTitle type="ip_adapter_layer" />
|
<Spacer />
|
||||||
<Spacer />
|
<LayerDeleteButton layerId={layerId} />
|
||||||
<LayerDeleteButton layerId={layerId} />
|
|
||||||
</Flex>
|
|
||||||
{isOpen && (
|
|
||||||
<Flex flexDir="column" gap={3} px={3} pb={3}>
|
|
||||||
<IPALayerIPAdapterWrapper layerId={layerId} />
|
|
||||||
</Flex>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
{isOpen && (
|
||||||
|
<Flex flexDir="column" gap={3} px={3} pb={3}>
|
||||||
|
<IPALayerIPAdapterWrapper layerId={layerId} />
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</LayerWrapper>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
import type { ChakraProps } from '@invoke-ai/ui-library';
|
||||||
|
import { Flex } from '@invoke-ai/ui-library';
|
||||||
|
import type { PropsWithChildren } from 'react';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
|
type Props = PropsWithChildren<{
|
||||||
|
onClick?: () => void;
|
||||||
|
borderColor: ChakraProps['bg'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export const LayerWrapper = memo(({ onClick, borderColor, children }: Props) => {
|
||||||
|
return (
|
||||||
|
<Flex gap={2} onClick={onClick} bg={borderColor} px={2} borderRadius="base" py="1px">
|
||||||
|
<Flex flexDir="column" w="full" bg="base.850" borderRadius="base">
|
||||||
|
{children}
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
LayerWrapper.displayName = 'LayerWrapper';
|
@ -7,6 +7,7 @@ import { LayerDeleteButton } from 'features/controlLayers/components/LayerCommon
|
|||||||
import { LayerMenu } from 'features/controlLayers/components/LayerCommon/LayerMenu';
|
import { LayerMenu } from 'features/controlLayers/components/LayerCommon/LayerMenu';
|
||||||
import { LayerTitle } from 'features/controlLayers/components/LayerCommon/LayerTitle';
|
import { LayerTitle } from 'features/controlLayers/components/LayerCommon/LayerTitle';
|
||||||
import { LayerVisibilityToggle } from 'features/controlLayers/components/LayerCommon/LayerVisibilityToggle';
|
import { LayerVisibilityToggle } from 'features/controlLayers/components/LayerCommon/LayerVisibilityToggle';
|
||||||
|
import { LayerWrapper } from 'features/controlLayers/components/LayerCommon/LayerWrapper';
|
||||||
import {
|
import {
|
||||||
isRegionalGuidanceLayer,
|
isRegionalGuidanceLayer,
|
||||||
layerSelected,
|
layerSelected,
|
||||||
@ -52,32 +53,30 @@ export const RGLayer = memo(({ layerId }: Props) => {
|
|||||||
dispatch(layerSelected(layerId));
|
dispatch(layerSelected(layerId));
|
||||||
}, [dispatch, layerId]);
|
}, [dispatch, layerId]);
|
||||||
return (
|
return (
|
||||||
<Flex gap={2} onClick={onClick} bg={isSelected ? color : 'base.800'} px={2} borderRadius="base" py="1px">
|
<LayerWrapper onClick={onClick} borderColor={isSelected ? color : 'base.800'}>
|
||||||
<Flex flexDir="column" w="full" bg="base.850" borderRadius="base">
|
<Flex gap={3} alignItems="center" p={3} cursor="pointer" onDoubleClick={onToggle}>
|
||||||
<Flex gap={3} alignItems="center" p={3} cursor="pointer" onDoubleClick={onToggle}>
|
<LayerVisibilityToggle layerId={layerId} />
|
||||||
<LayerVisibilityToggle layerId={layerId} />
|
<LayerTitle type="regional_guidance_layer" />
|
||||||
<LayerTitle type="regional_guidance_layer" />
|
<Spacer />
|
||||||
<Spacer />
|
{autoNegative === 'invert' && (
|
||||||
{autoNegative === 'invert' && (
|
<Badge color="base.300" bg="transparent" borderWidth={1} userSelect="none">
|
||||||
<Badge color="base.300" bg="transparent" borderWidth={1} userSelect="none">
|
{t('controlLayers.autoNegative')}
|
||||||
{t('controlLayers.autoNegative')}
|
</Badge>
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
<RGLayerColorPicker layerId={layerId} />
|
|
||||||
<RGLayerSettingsPopover layerId={layerId} />
|
|
||||||
<LayerMenu layerId={layerId} />
|
|
||||||
<LayerDeleteButton layerId={layerId} />
|
|
||||||
</Flex>
|
|
||||||
{isOpen && (
|
|
||||||
<Flex flexDir="column" gap={3} px={3} pb={3}>
|
|
||||||
{!hasPositivePrompt && !hasNegativePrompt && !hasIPAdapters && <AddPromptButtons layerId={layerId} />}
|
|
||||||
{hasPositivePrompt && <RGLayerPositivePrompt layerId={layerId} />}
|
|
||||||
{hasNegativePrompt && <RGLayerNegativePrompt layerId={layerId} />}
|
|
||||||
{hasIPAdapters && <RGLayerIPAdapterList layerId={layerId} />}
|
|
||||||
</Flex>
|
|
||||||
)}
|
)}
|
||||||
|
<RGLayerColorPicker layerId={layerId} />
|
||||||
|
<RGLayerSettingsPopover layerId={layerId} />
|
||||||
|
<LayerMenu layerId={layerId} />
|
||||||
|
<LayerDeleteButton layerId={layerId} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
{isOpen && (
|
||||||
|
<Flex flexDir="column" gap={3} px={3} pb={3}>
|
||||||
|
{!hasPositivePrompt && !hasNegativePrompt && !hasIPAdapters && <AddPromptButtons layerId={layerId} />}
|
||||||
|
{hasPositivePrompt && <RGLayerPositivePrompt layerId={layerId} />}
|
||||||
|
{hasNegativePrompt && <RGLayerNegativePrompt layerId={layerId} />}
|
||||||
|
{hasIPAdapters && <RGLayerIPAdapterList layerId={layerId} />}
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</LayerWrapper>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user