|
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine'; |
|
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; |
|
import type { ImageProps, SystemStyleObject } from '@invoke-ai/ui-library'; |
|
import { Image } from '@invoke-ai/ui-library'; |
|
import { useAppStore } from 'app/store/nanostores/store'; |
|
import { singleImageDndSource } from 'features/dnd/dnd'; |
|
import type { DndDragPreviewSingleImageState } from 'features/dnd/DndDragPreviewSingleImage'; |
|
import { createSingleImageDragPreview, setSingleImageDragPreview } from 'features/dnd/DndDragPreviewSingleImage'; |
|
import { firefoxDndFix } from 'features/dnd/util'; |
|
import { useImageContextMenu } from 'features/gallery/components/ImageContextMenu/ImageContextMenu'; |
|
import { memo, useEffect, useState } from 'react'; |
|
import type { ImageDTO } from 'services/api/types'; |
|
|
|
const sx = { |
|
objectFit: 'contain', |
|
maxW: 'full', |
|
maxH: 'full', |
|
borderRadius: 'base', |
|
cursor: 'grab', |
|
'&[data-is-dragging=true]': { |
|
opacity: 0.3, |
|
}, |
|
} satisfies SystemStyleObject; |
|
|
|
type Props = ImageProps & { |
|
imageDTO: ImageDTO; |
|
asThumbnail?: boolean; |
|
}; |
|
|
|
export const DndImage = memo(({ imageDTO, asThumbnail, ...rest }: Props) => { |
|
const store = useAppStore(); |
|
const [isDragging, setIsDragging] = useState(false); |
|
const [element, ref] = useState<HTMLImageElement | null>(null); |
|
const [dragPreviewState, setDragPreviewState] = useState<DndDragPreviewSingleImageState | null>(null); |
|
|
|
useEffect(() => { |
|
if (!element) { |
|
return; |
|
} |
|
return combine( |
|
firefoxDndFix(element), |
|
draggable({ |
|
element, |
|
getInitialData: () => singleImageDndSource.getData({ imageDTO }, imageDTO.image_name), |
|
onDragStart: () => { |
|
setIsDragging(true); |
|
}, |
|
onDrop: () => { |
|
setIsDragging(false); |
|
}, |
|
onGenerateDragPreview: (args) => { |
|
if (singleImageDndSource.typeGuard(args.source.data)) { |
|
setSingleImageDragPreview({ |
|
singleImageDndData: args.source.data, |
|
onGenerateDragPreviewArgs: args, |
|
setDragPreviewState, |
|
}); |
|
} |
|
}, |
|
}) |
|
); |
|
}, [imageDTO, element, store]); |
|
|
|
useImageContextMenu(imageDTO, element); |
|
|
|
return ( |
|
<> |
|
<Image |
|
role="button" |
|
ref={ref} |
|
src={asThumbnail ? imageDTO.thumbnail_url : imageDTO.image_url} |
|
fallbackSrc={asThumbnail ? undefined : imageDTO.thumbnail_url} |
|
w={imageDTO.width} |
|
sx={sx} |
|
data-is-dragging={isDragging} |
|
{...rest} |
|
/> |
|
{dragPreviewState?.type === 'single-image' ? createSingleImageDragPreview(dragPreviewState) : null} |
|
</> |
|
); |
|
}); |
|
|
|
DndImage.displayName = 'DndImage'; |
|
|