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';