68 lines
1.9 KiB
TypeScript
68 lines
1.9 KiB
TypeScript
'use client';
|
|
|
|
import { Upload } from 'lucide-react';
|
|
import { SUPPORTED_EXTENSIONS } from '../utils/wordCount';
|
|
|
|
interface DropZoneProps {
|
|
isDragging: boolean;
|
|
onDrop: (e: React.DragEvent) => void;
|
|
onDragOver: (e: React.DragEvent) => void;
|
|
onDragLeave: () => void;
|
|
onClick: () => void;
|
|
}
|
|
|
|
export function DropZone({
|
|
isDragging,
|
|
onDrop,
|
|
onDragOver,
|
|
onDragLeave,
|
|
onClick,
|
|
}: DropZoneProps) {
|
|
return (
|
|
<div
|
|
role="button"
|
|
tabIndex={0}
|
|
onClick={onClick}
|
|
onDrop={onDrop}
|
|
onDragOver={onDragOver}
|
|
onDragLeave={onDragLeave}
|
|
onKeyDown={(e) => e.key === 'Enter' && onClick()}
|
|
className={`
|
|
relative flex flex-col items-center justify-center gap-3
|
|
rounded-xl border-2 border-dashed px-6 py-2
|
|
cursor-pointer select-none transition-all duration-200 outline-none
|
|
focus-visible:ring-2 focus-visible:ring-blue-400 focus-visible:ring-offset-2
|
|
${
|
|
isDragging
|
|
? 'border-blue-400 bg-blue-50 scale-[1.01]'
|
|
: 'border-slate-200 bg-slate-50 hover:border-blue-300 hover:bg-blue-50/50'
|
|
}
|
|
`}
|
|
>
|
|
<div
|
|
className={`
|
|
w-12 h-12 rounded-full flex items-center justify-center
|
|
transition-all duration-200
|
|
${isDragging ? 'bg-blue-100 scale-110' : 'bg-white shadow-sm'}
|
|
`}
|
|
>
|
|
<Upload
|
|
size={22}
|
|
className={`transition-colors duration-200 ${
|
|
isDragging ? 'text-blue-500' : 'text-slate-400'
|
|
}`}
|
|
/>
|
|
</div>
|
|
|
|
<div className="text-center">
|
|
<p className="text-sm font-medium text-slate-700">
|
|
{isDragging ? 'Drop file here' : 'Drag & drop or click to browse'}
|
|
</p>
|
|
<p className="mt-1 text-xs text-slate-400">
|
|
Supported: {SUPPORTED_EXTENSIONS.join(', ')} · Max 50 MB
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|