diff --git a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx
index 959a70bc29f..7cc4eadc75f 100644
--- a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx
+++ b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx
@@ -1,4 +1,5 @@
import {
+ Box,
ChakraProps,
Flex,
Icon,
@@ -6,30 +7,28 @@ import {
useColorMode,
useColorModeValue,
} from '@chakra-ui/react';
-import { useCombinedRefs } from '@dnd-kit/utilities';
+import {
+ TypesafeDraggableData,
+ TypesafeDroppableData,
+ isValidDrop,
+ useDraggable,
+ useDroppable,
+} from 'app/components/ImageDnd/typesafeDnd';
import IAIIconButton from 'common/components/IAIIconButton';
import {
IAILoadingImageFallback,
IAINoContentFallback,
} from 'common/components/IAIImageFallback';
import ImageMetadataOverlay from 'common/components/ImageMetadataOverlay';
+import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
import { AnimatePresence } from 'framer-motion';
-import { MouseEvent, ReactElement, SyntheticEvent } from 'react';
-import { memo, useRef } from 'react';
+import { MouseEvent, ReactElement, SyntheticEvent, memo, useRef } from 'react';
import { FaImage, FaUndo, FaUpload } from 'react-icons/fa';
+import { PostUploadAction } from 'services/api/thunks/image';
import { ImageDTO } from 'services/api/types';
+import { mode } from 'theme/util/mode';
import { v4 as uuidv4 } from 'uuid';
import IAIDropOverlay from './IAIDropOverlay';
-import { PostUploadAction } from 'services/api/thunks/image';
-import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
-import { mode } from 'theme/util/mode';
-import {
- TypesafeDraggableData,
- TypesafeDroppableData,
- isValidDrop,
- useDraggable,
- useDroppable,
-} from 'app/components/ImageDnd/typesafeDnd';
type IAIDndImageProps = {
imageDTO: ImageDTO | undefined;
@@ -83,28 +82,6 @@ const IAIDndImage = (props: IAIDndImageProps) => {
const { colorMode } = useColorMode();
- const dndId = useRef(uuidv4());
-
- const {
- attributes,
- listeners,
- setNodeRef: setDraggableRef,
- isDragging,
- active,
- } = useDraggable({
- id: dndId.current,
- disabled: isDragDisabled || !imageDTO,
- data: draggableData,
- });
-
- const { isOver, setNodeRef: setDroppableRef } = useDroppable({
- id: dndId.current,
- disabled: isDropDisabled,
- data: droppableData,
- });
-
- const setDndRef = useCombinedRefs(setDroppableRef, setDraggableRef);
-
const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({
postUploadAction,
isDisabled: isUploadDisabled,
@@ -139,9 +116,6 @@ const IAIDndImage = (props: IAIDndImageProps) => {
userSelect: 'none',
cursor: isDragDisabled || !imageDTO ? 'default' : 'pointer',
}}
- {...attributes}
- {...listeners}
- ref={setDndRef}
>
{imageDTO && (
{
}}
>
}
@@ -225,13 +198,84 @@ const IAIDndImage = (props: IAIDndImageProps) => {
>
)}
{!imageDTO && isUploadDisabled && noContentFallback}
+
+
+
+ );
+};
+
+export default memo(IAIDndImage);
+
+type DroppableProps = {
+ dropLabel?: string;
+ disabled?: boolean;
+ data?: TypesafeDroppableData;
+};
+
+const Droppable = memo((props: DroppableProps) => {
+ const { dropLabel, data, disabled } = props;
+ const dndId = useRef(uuidv4());
+
+ const { isOver, setNodeRef, active } = useDroppable({
+ id: dndId.current,
+ disabled,
+ data,
+ });
+
+ return (
+
- {isValidDrop(droppableData, active) && !isDragging && (
+ {isValidDrop(data, active) && (
)}
-
+
);
+});
+
+Droppable.displayName = 'Droppable';
+
+type DraggableProps = {
+ disabled?: boolean;
+ data?: TypesafeDraggableData;
+ onClick?: (event: MouseEvent) => void;
};
-export default memo(IAIDndImage);
+const Draggable = memo((props: DraggableProps) => {
+ const { data, disabled, onClick } = props;
+ const dndId = useRef(uuidv4());
+
+ const { attributes, listeners, setNodeRef } = useDraggable({
+ id: dndId.current,
+ disabled,
+ data,
+ });
+
+ return (
+
+ );
+});
+
+Draggable.displayName = 'Draggable';