Files
papercrate/frontend/src/documents/interactions/useWorkspaceDragDrop.ts
T

81 lines
2.4 KiB
TypeScript

import { useEffect } from 'react';
import type { MutableRefObject } from 'react';
import {
isTagTransferEvent,
getActiveDragState,
} from '../features/tagging/tagTransfer';
interface UseWorkspaceDragDropArgs {
shellRef: MutableRefObject<HTMLElement | null>;
}
const useWorkspaceDragDrop = ({
shellRef,
}: UseWorkspaceDragDropArgs) => {
useEffect(() => {
const host = shellRef.current;
if (!host) {
return;
}
// Allow drop on workspace (global app shell)
const handleTagDragOver = (event: DragEvent) => {
if (!isTagTransferEvent(event)) {
return;
}
const { sourceDocId } = getActiveDragState();
// Only allow "Move" (removal) if the tag came from a document
if (sourceDocId) {
event.preventDefault(); // Necessary to allow dropping
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move';
}
}
};
const handleTagDragEnter = (event: DragEvent) => {
if (!isTagTransferEvent(event)) {
return;
}
const { sourceDocId } = getActiveDragState();
if (sourceDocId) {
event.preventDefault();
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move';
}
}
};
const handleTagDrop = (event: DragEvent) => {
if (!isTagTransferEvent(event)) {
return;
}
const { sourceDocId } = getActiveDragState();
if (sourceDocId) {
// Consume the event so the browser reports 'move' back to the source
event.preventDefault();
}
};
// Use bubbling (false) so children can stopPropagation
host.addEventListener('dragenter', handleTagDragEnter, false);
host.addEventListener('dragover', handleTagDragOver, false);
host.addEventListener('drop', handleTagDrop, false);
return () => {
host.removeEventListener('dragenter', handleTagDragEnter, false);
host.removeEventListener('dragover', handleTagDragOver, false);
host.removeEventListener('drop', handleTagDrop, false);
};
}, [shellRef]);
return {};
};
export default useWorkspaceDragDrop;