fix(files): make dropped-file handling explicit
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import { i18nMessage } from "../i18n/LanguageContext";import { useRef, useState, type CSSProperties, type ReactNode } from "react";
|
||||
import { i18nMessage } from "../i18n/LanguageContext";import { useRef, useState, type CSSProperties, type DragEvent as ReactDragEvent, type ReactNode } from "react";
|
||||
import { UploadCloud } from "lucide-react";
|
||||
import { resolveDroppedFiles } from "./resolveDroppedFiles";
|
||||
|
||||
type RejectedDropReason = "disabled" | "empty" | "unreadable";
|
||||
|
||||
export type FileDropZoneProps = {
|
||||
accept?: string;
|
||||
@@ -14,6 +17,7 @@ export type FileDropZoneProps = {
|
||||
note?: ReactNode;
|
||||
className?: string;
|
||||
inputLabel?: string;
|
||||
onRejectedDrop?: (reason: RejectedDropReason) => void;
|
||||
onFiles: (files: File[]) => void | Promise<void>;
|
||||
};
|
||||
|
||||
@@ -30,6 +34,7 @@ export default function FileDropZone({
|
||||
note,
|
||||
className = "",
|
||||
inputLabel = "i18n:govoplan-core.drop_files_here_or_click_to_select_files.7eda8608",
|
||||
onRejectedDrop,
|
||||
onFiles
|
||||
}: FileDropZoneProps) {
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
@@ -52,6 +57,13 @@ export default function FileDropZone({
|
||||
}
|
||||
}
|
||||
|
||||
function prepareFileDrag(event: ReactDragEvent<HTMLDivElement>) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.dataTransfer.dropEffect = interactionDisabled ? "none" : "copy";
|
||||
if (!interactionDisabled) setDragActive(true);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -70,15 +82,29 @@ export default function FileDropZone({
|
||||
inputRef.current?.click();
|
||||
}
|
||||
}}
|
||||
onDragOver={(event) => {
|
||||
onDragEnter={prepareFileDrag}
|
||||
onDragOver={prepareFileDrag}
|
||||
onDragLeave={(event) => {
|
||||
event.preventDefault();
|
||||
if (!interactionDisabled) setDragActive(true);
|
||||
event.stopPropagation();
|
||||
if (event.relatedTarget instanceof Node && event.currentTarget.contains(event.relatedTarget)) return;
|
||||
setDragActive(false);
|
||||
}}
|
||||
onDragLeave={() => setDragActive(false)}
|
||||
onDrop={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setDragActive(false);
|
||||
if (!interactionDisabled) void handleFiles(event.dataTransfer.files);
|
||||
if (interactionDisabled) {
|
||||
onRejectedDrop?.("disabled");
|
||||
return;
|
||||
}
|
||||
void resolveDroppedFiles(event.dataTransfer).then((files) => {
|
||||
if (files.length === 0) {
|
||||
onRejectedDrop?.("empty");
|
||||
return;
|
||||
}
|
||||
void handleFiles(files);
|
||||
}).catch(() => onRejectedDrop?.("unreadable"));
|
||||
}}>
|
||||
|
||||
{showProgress ?
|
||||
@@ -110,4 +136,4 @@ export default function FileDropZone({
|
||||
|
||||
</>);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user