function DropZone({ onFilesAccepted }) {
const [isDragging, setIsDragging]
= useState(false);
const handleDragOver = (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
setIsDragging(true);
};
const handleDragLeave = (e) => {
if (!e.currentTarget.contains(
e.relatedTarget)) {
setIsDragging(false);
}
};
const handleDrop = (e) => {
e.preventDefault();
setIsDragging(false);
const files = [...e.dataTransfer.files]
.filter(f =>
f.type.startsWith('image/'));
if (files.length === 0) {
alert('Only image files accepted');
return;
}
onFilesAccepted(files);
};
return (
<div
className={`dropzone
${isDragging ? 'active' : ''}`}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
{isDragging
? '📸 Drop images here!'
: 'Drag images here or click'}
</div>
);
}
function validateAndPreview(files) {
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
const ALLOWED = [
'image/png', 'image/jpeg',
'image/webp', 'image/gif'
];
return files
.filter(file => {
if (!ALLOWED.includes(file.type)) {
console.warn(
`Rejected: ${file.name} — ` +
`invalid type`);
return false;
}
if (file.size > MAX_SIZE) {
console.warn(
`Rejected: ${file.name} — ` +
`exceeds 10MB`);
return false;
}
return true;
})
.map(file => ({
file,
previewUrl:
URL.createObjectURL(file)
}));
}
function loadImageToCanvas(file, canvas) {
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(img.src);
};
img.src = URL.createObjectURL(file);
}
Drop multiple images at once → show thumbnail previews in a strip below the canvas. Click a thumbnail → load that image onto the main canvas. Show file name and size under each thumbnail.
git switch -c feature/PIXELCRAFT-060-drag-drop
git add src/
git commit -m "Add drag-and-drop image upload with validation (PIXELCRAFT-060)"
git push origin feature/PIXELCRAFT-060-drag-drop
# PR → Review → Merge → Close ticket ✅
The browser is a rich application platform.
Drag and Drop is one of many native Web APIs that eliminate the need for external libraries.