import React, { createContext, useState, useEffect, useMemo, ReactNode, useCallback, } from "react"; import { processDroppedFiles } from "@/lib/UrdfDragAndDrop"; import { useUrdf } from "@/hooks/useUrdf"; export type DragAndDropContextType = { isDragging: boolean; setIsDragging: (isDragging: boolean) => void; handleDrop: (e: DragEvent) => Promise; }; export const DragAndDropContext = createContext< DragAndDropContextType | undefined >(undefined); interface DragAndDropProviderProps { children: ReactNode; } export const DragAndDropProvider: React.FC = ({ children, }) => { const [isDragging, setIsDragging] = useState(false); // Get the Urdf context const { urdfProcessor, processUrdfFiles } = useUrdf(); const handleDragOver = (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); }; const handleDragEnter = (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(true); }; const handleDragLeave = (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); // Only set isDragging to false if we're leaving the document // This prevents flickering when moving between elements if (!e.relatedTarget || !(e.relatedTarget as Element).closest("html")) { setIsDragging(false); } }; const handleDrop = useCallback( async (e: DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); if (!e.dataTransfer || !urdfProcessor) return; try { const { availableModels, files } = await processDroppedFiles( e.dataTransfer, urdfProcessor ); await processUrdfFiles(files, availableModels); } catch (error) { console.error("Error in handleDrop:", error); } }, [urdfProcessor, processUrdfFiles] ); // Set up global event listeners useEffect(() => { document.addEventListener("dragover", handleDragOver); document.addEventListener("dragenter", handleDragEnter); document.addEventListener("dragleave", handleDragLeave); document.addEventListener("drop", handleDrop); return () => { document.removeEventListener("dragover", handleDragOver); document.removeEventListener("dragenter", handleDragEnter); document.removeEventListener("dragleave", handleDragLeave); document.removeEventListener("drop", handleDrop); }; }, [handleDrop]); // Re-register when handleDrop changes const value = useMemo( () => ({ isDragging, setIsDragging, handleDrop }), [isDragging, handleDrop] ); return ( {children} {isDragging && (
Drop Urdf Files Here

Release to upload your robot model

)}
); };