Files
MattrixwvReactComponents/lib/component/input/file/DragAndDropFileInput.tsx

85 lines
2.0 KiB
TypeScript

import type { FileInputProps } from "$/types/InputTypes";
import { humanReadableBytes } from "$/util/FileUtil";
import clsx from "clsx";
import { useEffect, useRef, useState } from "react";
export default function DragAndDropFileInput({
id,
className,
name,
minSize,
maxSize,
showFileName,
showSize,
onChange,
disabled,
children
}: FileInputProps){
const [ file, setFile ] = useState<File>();
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
onChange?.(file);
}, [ file, onChange ]);
return (
<label
className={clsx(
"flex flex-col items-center justify-center border-2 rounded-lg w-full h-full cursor-pointer",
className
)}
onDragOver={(e) => e.preventDefault()}
onDrop={(e) => {
e.preventDefault();
setFile(e.dataTransfer.files[0]);
if(inputRef.current){ inputRef.current.files = e.dataTransfer.files; }
}}
>
<input
ref={inputRef}
type="file"
id={id}
className="sr-only"
name={name}
onChange={(e) => setFile(e.target.files?.[0])}
disabled={disabled}
/>
<div
className="flex flex-col items-center justify-between w-full h-full px-2"
>
{children}
<div
className="flex flex-row items-center justify-between gap-x-8 w-full"
>
{
showFileName &&
<div
className="text-center"
>
{file?.name}
</div>
}
{
showSize &&
<div
className={clsx(
{
"text-red-600": minSize && file?.size && file?.size < minSize,
"text-red-600 ": maxSize && file?.size && file?.size > maxSize,
"text-green-600": minSize && !maxSize && file?.size && file?.size > minSize,
"text-green-600 ": !minSize && maxSize && file?.size && file?.size < maxSize,
" text-green-600": minSize && maxSize && file?.size && file?.size > minSize && file?.size < maxSize
}
)}
>
{humanReadableBytes(file?.size ?? 0)}
</div>
}
</div>
</div>
</label>
);
}