@shipstatic/drop 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -27
- package/dist/index.cjs +136 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -9
- package/dist/index.d.ts +23 -9
- package/dist/index.js +137 -91
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -52,6 +52,26 @@ interface ProcessedFile extends StaticFile {
|
|
|
52
52
|
/** Upload progress (0-100) - only set during upload */
|
|
53
53
|
progress?: number;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* State machine values for the drop hook
|
|
57
|
+
*/
|
|
58
|
+
type DropStateValue = 'idle' | 'dragging' | 'processing' | 'ready' | 'error';
|
|
59
|
+
/**
|
|
60
|
+
* Status information with title and details
|
|
61
|
+
*/
|
|
62
|
+
interface DropStatus {
|
|
63
|
+
title: string;
|
|
64
|
+
details: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* State machine state for the drop hook
|
|
68
|
+
*/
|
|
69
|
+
interface DropState {
|
|
70
|
+
value: DropStateValue;
|
|
71
|
+
files: ProcessedFile[];
|
|
72
|
+
sourceName: string;
|
|
73
|
+
status: DropStatus | null;
|
|
74
|
+
}
|
|
55
75
|
|
|
56
76
|
interface DropOptions {
|
|
57
77
|
/** Ship SDK instance (required for validation) */
|
|
@@ -64,18 +84,12 @@ interface DropOptions {
|
|
|
64
84
|
stripPrefix?: boolean;
|
|
65
85
|
}
|
|
66
86
|
interface DropReturn {
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
/** Name of the source (file/folder/ZIP) that was dropped/selected */
|
|
70
|
-
sourceName: string;
|
|
71
|
-
/** Current status text */
|
|
72
|
-
statusText: string;
|
|
87
|
+
/** Current state of the drop hook */
|
|
88
|
+
state: DropState;
|
|
73
89
|
/** Whether currently processing files (ZIP extraction, etc.) */
|
|
74
90
|
isProcessing: boolean;
|
|
75
91
|
/** Whether user is currently dragging over the dropzone */
|
|
76
92
|
isDragging: boolean;
|
|
77
|
-
/** Last validation error if any */
|
|
78
|
-
validationError: ClientError | null;
|
|
79
93
|
/** Get props to spread on dropzone element (handles drag & drop) */
|
|
80
94
|
getDropzoneProps: () => {
|
|
81
95
|
onDragOver: (e: React.DragEvent) => void;
|
|
@@ -189,4 +203,4 @@ declare function normalizePath(path: string): string;
|
|
|
189
203
|
*/
|
|
190
204
|
declare function isZipFile(file: File): boolean;
|
|
191
205
|
|
|
192
|
-
export { type ClientError, type DropOptions, type DropReturn, FILE_STATUSES, type FileStatus, type ProcessedFile, type ZipExtractionResult, createProcessedFile, extractZipToFiles, formatFileSize, getValidFiles, isZipFile, normalizePath, stripCommonPrefix, useDrop };
|
|
206
|
+
export { type ClientError, type DropOptions, type DropReturn, type DropState, type DropStateValue, type DropStatus, FILE_STATUSES, type FileStatus, type ProcessedFile, type ZipExtractionResult, createProcessedFile, extractZipToFiles, formatFileSize, getValidFiles, isZipFile, normalizePath, stripCommonPrefix, useDrop };
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,26 @@ interface ProcessedFile extends StaticFile {
|
|
|
52
52
|
/** Upload progress (0-100) - only set during upload */
|
|
53
53
|
progress?: number;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* State machine values for the drop hook
|
|
57
|
+
*/
|
|
58
|
+
type DropStateValue = 'idle' | 'dragging' | 'processing' | 'ready' | 'error';
|
|
59
|
+
/**
|
|
60
|
+
* Status information with title and details
|
|
61
|
+
*/
|
|
62
|
+
interface DropStatus {
|
|
63
|
+
title: string;
|
|
64
|
+
details: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* State machine state for the drop hook
|
|
68
|
+
*/
|
|
69
|
+
interface DropState {
|
|
70
|
+
value: DropStateValue;
|
|
71
|
+
files: ProcessedFile[];
|
|
72
|
+
sourceName: string;
|
|
73
|
+
status: DropStatus | null;
|
|
74
|
+
}
|
|
55
75
|
|
|
56
76
|
interface DropOptions {
|
|
57
77
|
/** Ship SDK instance (required for validation) */
|
|
@@ -64,18 +84,12 @@ interface DropOptions {
|
|
|
64
84
|
stripPrefix?: boolean;
|
|
65
85
|
}
|
|
66
86
|
interface DropReturn {
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
/** Name of the source (file/folder/ZIP) that was dropped/selected */
|
|
70
|
-
sourceName: string;
|
|
71
|
-
/** Current status text */
|
|
72
|
-
statusText: string;
|
|
87
|
+
/** Current state of the drop hook */
|
|
88
|
+
state: DropState;
|
|
73
89
|
/** Whether currently processing files (ZIP extraction, etc.) */
|
|
74
90
|
isProcessing: boolean;
|
|
75
91
|
/** Whether user is currently dragging over the dropzone */
|
|
76
92
|
isDragging: boolean;
|
|
77
|
-
/** Last validation error if any */
|
|
78
|
-
validationError: ClientError | null;
|
|
79
93
|
/** Get props to spread on dropzone element (handles drag & drop) */
|
|
80
94
|
getDropzoneProps: () => {
|
|
81
95
|
onDragOver: (e: React.DragEvent) => void;
|
|
@@ -189,4 +203,4 @@ declare function normalizePath(path: string): string;
|
|
|
189
203
|
*/
|
|
190
204
|
declare function isZipFile(file: File): boolean;
|
|
191
205
|
|
|
192
|
-
export { type ClientError, type DropOptions, type DropReturn, FILE_STATUSES, type FileStatus, type ProcessedFile, type ZipExtractionResult, createProcessedFile, extractZipToFiles, formatFileSize, getValidFiles, isZipFile, normalizePath, stripCommonPrefix, useDrop };
|
|
206
|
+
export { type ClientError, type DropOptions, type DropReturn, type DropState, type DropStateValue, type DropStatus, FILE_STATUSES, type FileStatus, type ProcessedFile, type ZipExtractionResult, createProcessedFile, extractZipToFiles, formatFileSize, getValidFiles, isZipFile, normalizePath, stripCommonPrefix, useDrop };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useRef, useCallback } from 'react';
|
|
1
|
+
import { useState, useRef, useMemo, useCallback } from 'react';
|
|
2
2
|
import { formatFileSize as formatFileSize$1, getValidFiles as getValidFiles$1, filterJunk, validateFiles } from '@shipstatic/ship';
|
|
3
3
|
|
|
4
4
|
var __create = Object.create;
|
|
@@ -35,9 +35,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
35
35
|
|
|
36
36
|
// node_modules/.pnpm/jszip@3.10.1/node_modules/jszip/dist/jszip.min.js
|
|
37
37
|
var require_jszip_min = __commonJS({
|
|
38
|
-
"node_modules/.pnpm/jszip@3.10.1/node_modules/jszip/dist/jszip.min.js"(exports, module) {
|
|
38
|
+
"node_modules/.pnpm/jszip@3.10.1/node_modules/jszip/dist/jszip.min.js"(exports$1, module) {
|
|
39
39
|
!(function(e) {
|
|
40
|
-
if ("object" == typeof exports && "undefined" != typeof module) module.exports = e();
|
|
40
|
+
if ("object" == typeof exports$1 && "undefined" != typeof module) module.exports = e();
|
|
41
41
|
else if ("function" == typeof define && define.amd) define([], e);
|
|
42
42
|
else {
|
|
43
43
|
("undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : this).JSZip = e();
|
|
@@ -2347,7 +2347,7 @@ var require_jszip_min = __commonJS({
|
|
|
2347
2347
|
|
|
2348
2348
|
// node_modules/.pnpm/mime-db@1.54.0/node_modules/mime-db/db.json
|
|
2349
2349
|
var require_db = __commonJS({
|
|
2350
|
-
"node_modules/.pnpm/mime-db@1.54.0/node_modules/mime-db/db.json"(exports, module) {
|
|
2350
|
+
"node_modules/.pnpm/mime-db@1.54.0/node_modules/mime-db/db.json"(exports$1, module) {
|
|
2351
2351
|
module.exports = {
|
|
2352
2352
|
"application/1d-interleaved-parityfec": {
|
|
2353
2353
|
source: "iana"
|
|
@@ -11695,7 +11695,7 @@ var require_db = __commonJS({
|
|
|
11695
11695
|
|
|
11696
11696
|
// node_modules/.pnpm/mime-db@1.54.0/node_modules/mime-db/index.js
|
|
11697
11697
|
var require_mime_db = __commonJS({
|
|
11698
|
-
"node_modules/.pnpm/mime-db@1.54.0/node_modules/mime-db/index.js"(exports, module) {
|
|
11698
|
+
"node_modules/.pnpm/mime-db@1.54.0/node_modules/mime-db/index.js"(exports$1, module) {
|
|
11699
11699
|
module.exports = require_db();
|
|
11700
11700
|
}
|
|
11701
11701
|
});
|
|
@@ -11833,35 +11833,39 @@ function stripCommonPrefix(files) {
|
|
|
11833
11833
|
}));
|
|
11834
11834
|
}
|
|
11835
11835
|
async function traverseFileTree(entry, files, currentPath = "") {
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
const
|
|
11851
|
-
|
|
11852
|
-
|
|
11836
|
+
try {
|
|
11837
|
+
if (entry.isFile) {
|
|
11838
|
+
const file = await new Promise((resolve, reject) => {
|
|
11839
|
+
entry.file(resolve, reject);
|
|
11840
|
+
});
|
|
11841
|
+
const relativePath = currentPath ? `${currentPath}/${file.name}` : file.name;
|
|
11842
|
+
Object.defineProperty(file, "webkitRelativePath", {
|
|
11843
|
+
value: relativePath,
|
|
11844
|
+
writable: false
|
|
11845
|
+
});
|
|
11846
|
+
files.push(file);
|
|
11847
|
+
} else if (entry.isDirectory) {
|
|
11848
|
+
const dirReader = entry.createReader();
|
|
11849
|
+
let allEntries = [];
|
|
11850
|
+
const readEntriesBatch = async () => {
|
|
11851
|
+
const batch = await new Promise(
|
|
11852
|
+
(resolve, reject) => {
|
|
11853
|
+
dirReader.readEntries(resolve, reject);
|
|
11854
|
+
}
|
|
11855
|
+
);
|
|
11856
|
+
if (batch.length > 0) {
|
|
11857
|
+
allEntries = allEntries.concat(batch);
|
|
11858
|
+
await readEntriesBatch();
|
|
11853
11859
|
}
|
|
11854
|
-
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11860
|
+
};
|
|
11861
|
+
await readEntriesBatch();
|
|
11862
|
+
for (const childEntry of allEntries) {
|
|
11863
|
+
const entryPath = childEntry.isDirectory ? currentPath ? `${currentPath}/${childEntry.name}` : childEntry.name : currentPath;
|
|
11864
|
+
await traverseFileTree(childEntry, files, entryPath);
|
|
11858
11865
|
}
|
|
11859
|
-
};
|
|
11860
|
-
await readEntriesBatch();
|
|
11861
|
-
for (const childEntry of allEntries) {
|
|
11862
|
-
const entryPath = childEntry.isDirectory ? currentPath ? `${currentPath}/${childEntry.name}` : childEntry.name : currentPath;
|
|
11863
|
-
await traverseFileTree(childEntry, files, entryPath);
|
|
11864
11866
|
}
|
|
11867
|
+
} catch (error) {
|
|
11868
|
+
console.warn(`Error traversing file tree for entry ${entry.name}:`, error);
|
|
11865
11869
|
}
|
|
11866
11870
|
}
|
|
11867
11871
|
function useDrop(options) {
|
|
@@ -11871,28 +11875,32 @@ function useDrop(options) {
|
|
|
11871
11875
|
onFilesReady,
|
|
11872
11876
|
stripPrefix = true
|
|
11873
11877
|
} = options;
|
|
11874
|
-
const
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11878
|
+
const initialState = {
|
|
11879
|
+
value: "idle",
|
|
11880
|
+
files: [],
|
|
11881
|
+
sourceName: "",
|
|
11882
|
+
status: null
|
|
11883
|
+
};
|
|
11884
|
+
const [state, setState] = useState(initialState);
|
|
11880
11885
|
const isProcessingRef = useRef(false);
|
|
11881
11886
|
const inputRef = useRef(null);
|
|
11887
|
+
const isProcessing = useMemo(() => state.value === "processing", [state.value]);
|
|
11888
|
+
const isDragging = useMemo(() => state.value === "dragging", [state.value]);
|
|
11882
11889
|
const processFiles = useCallback(async (newFiles) => {
|
|
11883
11890
|
if (isProcessingRef.current) {
|
|
11884
11891
|
console.warn("File processing already in progress. Ignoring duplicate call.");
|
|
11885
11892
|
return;
|
|
11886
11893
|
}
|
|
11887
11894
|
if (!newFiles || newFiles.length === 0) {
|
|
11888
|
-
setStatusText("No files selected.");
|
|
11889
11895
|
return;
|
|
11890
11896
|
}
|
|
11891
11897
|
isProcessingRef.current = true;
|
|
11892
|
-
|
|
11893
|
-
|
|
11894
|
-
|
|
11895
|
-
|
|
11898
|
+
setState({
|
|
11899
|
+
value: "processing",
|
|
11900
|
+
files: [],
|
|
11901
|
+
sourceName: "",
|
|
11902
|
+
status: { title: "Processing...", details: "Validating and preparing files." }
|
|
11903
|
+
});
|
|
11896
11904
|
try {
|
|
11897
11905
|
let detectedSourceName = "";
|
|
11898
11906
|
if (newFiles.length === 1 && isZipFile(newFiles[0])) {
|
|
@@ -11905,12 +11913,14 @@ function useDrop(options) {
|
|
|
11905
11913
|
detectedSourceName = newFiles[0].name;
|
|
11906
11914
|
}
|
|
11907
11915
|
}
|
|
11908
|
-
setSourceName(detectedSourceName);
|
|
11909
11916
|
const allFiles = [];
|
|
11910
11917
|
const shouldExtractZip = newFiles.length === 1 && isZipFile(newFiles[0]);
|
|
11911
11918
|
if (shouldExtractZip) {
|
|
11912
11919
|
const zipFile = newFiles[0];
|
|
11913
|
-
|
|
11920
|
+
setState((prev) => ({
|
|
11921
|
+
...prev,
|
|
11922
|
+
status: { title: "Extracting...", details: `Extracting ${zipFile.name}...` }
|
|
11923
|
+
}));
|
|
11914
11924
|
const { files: extractedFiles, errors } = await extractZipToFiles(zipFile);
|
|
11915
11925
|
if (errors.length > 0) {
|
|
11916
11926
|
console.warn("ZIP extraction errors:", errors);
|
|
@@ -11926,29 +11936,44 @@ function useDrop(options) {
|
|
|
11926
11936
|
const filePaths = allFiles.map(getFilePath);
|
|
11927
11937
|
const validPaths = new Set(filterJunk(filePaths));
|
|
11928
11938
|
const cleanFiles = allFiles.filter((f) => validPaths.has(getFilePath(f)));
|
|
11929
|
-
|
|
11939
|
+
setState((prev) => ({
|
|
11940
|
+
...prev,
|
|
11941
|
+
status: { title: "Processing...", details: "Processing files..." }
|
|
11942
|
+
}));
|
|
11930
11943
|
const processedFiles = await Promise.all(
|
|
11931
11944
|
cleanFiles.map((file) => createProcessedFile(file))
|
|
11932
11945
|
);
|
|
11933
11946
|
const finalFiles = stripPrefix ? stripCommonPrefix(processedFiles) : processedFiles;
|
|
11934
11947
|
const config = await ship.getConfig();
|
|
11935
11948
|
const validation = validateFiles(finalFiles, config);
|
|
11936
|
-
setFiles(validation.files);
|
|
11937
|
-
setValidationError(validation.error);
|
|
11938
11949
|
if (validation.error) {
|
|
11939
|
-
|
|
11950
|
+
setState({
|
|
11951
|
+
value: "error",
|
|
11952
|
+
files: validation.files,
|
|
11953
|
+
sourceName: detectedSourceName,
|
|
11954
|
+
status: { title: validation.error.error, details: validation.error.details }
|
|
11955
|
+
});
|
|
11940
11956
|
onValidationError?.(validation.error);
|
|
11941
11957
|
} else if (validation.validFiles.length > 0) {
|
|
11942
|
-
|
|
11958
|
+
setState({
|
|
11959
|
+
value: "ready",
|
|
11960
|
+
files: validation.files,
|
|
11961
|
+
sourceName: detectedSourceName,
|
|
11962
|
+
status: { title: "Ready", details: `${validation.validFiles.length} file(s) are ready.` }
|
|
11963
|
+
});
|
|
11943
11964
|
onFilesReady?.(validation.validFiles);
|
|
11944
11965
|
} else {
|
|
11945
11966
|
const noValidError = {
|
|
11946
11967
|
error: "No Valid Files",
|
|
11947
|
-
details: "
|
|
11968
|
+
details: "None of the provided files could be processed.",
|
|
11948
11969
|
isClientError: true
|
|
11949
11970
|
};
|
|
11950
|
-
|
|
11951
|
-
|
|
11971
|
+
setState({
|
|
11972
|
+
value: "error",
|
|
11973
|
+
files: validation.files,
|
|
11974
|
+
sourceName: detectedSourceName,
|
|
11975
|
+
status: { title: noValidError.error, details: noValidError.details }
|
|
11976
|
+
});
|
|
11952
11977
|
onValidationError?.(noValidError);
|
|
11953
11978
|
}
|
|
11954
11979
|
} catch (error) {
|
|
@@ -11957,69 +11982,92 @@ function useDrop(options) {
|
|
|
11957
11982
|
details: `Failed to process files: ${error instanceof Error ? error.message : String(error)}`,
|
|
11958
11983
|
isClientError: true
|
|
11959
11984
|
};
|
|
11960
|
-
|
|
11961
|
-
|
|
11985
|
+
setState((prev) => ({
|
|
11986
|
+
...prev,
|
|
11987
|
+
value: "error",
|
|
11988
|
+
status: { title: processingError.error, details: processingError.details }
|
|
11989
|
+
}));
|
|
11962
11990
|
onValidationError?.(processingError);
|
|
11963
11991
|
} finally {
|
|
11964
11992
|
isProcessingRef.current = false;
|
|
11965
|
-
setIsProcessing(false);
|
|
11966
11993
|
}
|
|
11967
11994
|
}, [ship, onValidationError, onFilesReady, stripPrefix]);
|
|
11968
11995
|
const clearAll = useCallback(() => {
|
|
11969
|
-
|
|
11970
|
-
setSourceName("");
|
|
11971
|
-
setStatusText("");
|
|
11972
|
-
setValidationError(null);
|
|
11973
|
-
setIsDragging(false);
|
|
11996
|
+
setState(initialState);
|
|
11974
11997
|
isProcessingRef.current = false;
|
|
11975
|
-
setIsProcessing(false);
|
|
11976
11998
|
}, []);
|
|
11977
11999
|
const getValidFilesCallback = useCallback(() => {
|
|
11978
|
-
return getValidFiles(files);
|
|
11979
|
-
}, [files]);
|
|
11980
|
-
const updateFileStatus = useCallback((fileId,
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
12000
|
+
return getValidFiles(state.files);
|
|
12001
|
+
}, [state.files]);
|
|
12002
|
+
const updateFileStatus = useCallback((fileId, fileState) => {
|
|
12003
|
+
setState((prev) => ({
|
|
12004
|
+
...prev,
|
|
12005
|
+
files: prev.files.map(
|
|
12006
|
+
(file) => file.id === fileId ? { ...file, ...fileState } : file
|
|
12007
|
+
)
|
|
12008
|
+
}));
|
|
11984
12009
|
}, []);
|
|
11985
12010
|
const handleDragOver = useCallback((e) => {
|
|
11986
12011
|
e.preventDefault();
|
|
11987
|
-
|
|
12012
|
+
setState((prev) => {
|
|
12013
|
+
if (prev.value === "idle" || prev.value === "ready" || prev.value === "error") {
|
|
12014
|
+
return { ...prev, value: "dragging" };
|
|
12015
|
+
}
|
|
12016
|
+
return prev;
|
|
12017
|
+
});
|
|
11988
12018
|
}, []);
|
|
11989
12019
|
const handleDragLeave = useCallback((e) => {
|
|
11990
12020
|
e.preventDefault();
|
|
11991
|
-
|
|
12021
|
+
setState((prev) => {
|
|
12022
|
+
if (prev.value !== "dragging") return prev;
|
|
12023
|
+
const nextValue = prev.files.length > 0 ? prev.status?.title === "Ready" ? "ready" : "error" : "idle";
|
|
12024
|
+
return { ...prev, value: nextValue };
|
|
12025
|
+
});
|
|
11992
12026
|
}, []);
|
|
11993
12027
|
const handleDrop = useCallback(async (e) => {
|
|
11994
12028
|
e.preventDefault();
|
|
11995
|
-
setIsDragging(false);
|
|
11996
12029
|
const items = Array.from(e.dataTransfer.items);
|
|
11997
|
-
const
|
|
12030
|
+
const files = [];
|
|
11998
12031
|
let hasEntries = false;
|
|
11999
12032
|
for (const item of items) {
|
|
12000
12033
|
if (item.kind === "file") {
|
|
12001
|
-
|
|
12002
|
-
|
|
12003
|
-
|
|
12004
|
-
|
|
12005
|
-
|
|
12006
|
-
|
|
12007
|
-
|
|
12008
|
-
|
|
12034
|
+
try {
|
|
12035
|
+
const entry = item.webkitGetAsEntry?.();
|
|
12036
|
+
if (entry) {
|
|
12037
|
+
hasEntries = true;
|
|
12038
|
+
await traverseFileTree(
|
|
12039
|
+
entry,
|
|
12040
|
+
files,
|
|
12041
|
+
entry.isDirectory ? entry.name : ""
|
|
12042
|
+
);
|
|
12043
|
+
} else {
|
|
12044
|
+
const file = item.getAsFile();
|
|
12045
|
+
if (file) {
|
|
12046
|
+
files.push(file);
|
|
12047
|
+
}
|
|
12048
|
+
}
|
|
12049
|
+
} catch (error) {
|
|
12050
|
+
console.warn("Error processing drop item:", error);
|
|
12051
|
+
const file = item.getAsFile();
|
|
12052
|
+
if (file) {
|
|
12053
|
+
files.push(file);
|
|
12054
|
+
}
|
|
12009
12055
|
}
|
|
12010
12056
|
}
|
|
12011
12057
|
}
|
|
12012
12058
|
if (!hasEntries && e.dataTransfer.files.length > 0) {
|
|
12013
|
-
|
|
12059
|
+
files.push(...Array.from(e.dataTransfer.files));
|
|
12014
12060
|
}
|
|
12015
|
-
if (
|
|
12016
|
-
await processFiles(
|
|
12061
|
+
if (files.length > 0) {
|
|
12062
|
+
await processFiles(files);
|
|
12063
|
+
} else if (state.value === "dragging") {
|
|
12064
|
+
setState((prev) => ({ ...prev, value: "idle" }));
|
|
12017
12065
|
}
|
|
12018
|
-
}, [processFiles]);
|
|
12066
|
+
}, [processFiles, state.value]);
|
|
12019
12067
|
const handleInputChange = useCallback((e) => {
|
|
12020
|
-
const
|
|
12021
|
-
if (
|
|
12022
|
-
processFiles(
|
|
12068
|
+
const files = Array.from(e.target.files || []);
|
|
12069
|
+
if (files.length > 0) {
|
|
12070
|
+
processFiles(files);
|
|
12023
12071
|
}
|
|
12024
12072
|
}, [processFiles]);
|
|
12025
12073
|
const open = useCallback(() => {
|
|
@@ -12040,13 +12088,11 @@ function useDrop(options) {
|
|
|
12040
12088
|
onChange: handleInputChange
|
|
12041
12089
|
}), [handleInputChange]);
|
|
12042
12090
|
return {
|
|
12043
|
-
// State
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
statusText,
|
|
12091
|
+
// State machine
|
|
12092
|
+
state,
|
|
12093
|
+
// Convenience getters (computed from state)
|
|
12047
12094
|
isProcessing,
|
|
12048
12095
|
isDragging,
|
|
12049
|
-
validationError,
|
|
12050
12096
|
// Primary API: Prop getters
|
|
12051
12097
|
getDropzoneProps,
|
|
12052
12098
|
getInputProps,
|