@shipstatic/drop 0.1.7 → 0.1.9
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 +69 -43
- package/dist/index.cjs +68 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -10
- package/dist/index.d.ts +19 -10
- package/dist/index.js +69 -47
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.d.cts
CHANGED
|
@@ -62,6 +62,7 @@ type DropStateValue = 'idle' | 'dragging' | 'processing' | 'ready' | 'error';
|
|
|
62
62
|
interface DropStatus {
|
|
63
63
|
title: string;
|
|
64
64
|
details: string;
|
|
65
|
+
errors?: string[];
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
68
|
* State machine state for the drop hook
|
|
@@ -84,12 +85,21 @@ interface DropOptions {
|
|
|
84
85
|
stripPrefix?: boolean;
|
|
85
86
|
}
|
|
86
87
|
interface DropReturn {
|
|
87
|
-
/** Current
|
|
88
|
-
|
|
88
|
+
/** Current phase of the state machine */
|
|
89
|
+
phase: DropStateValue;
|
|
89
90
|
/** Whether currently processing files (ZIP extraction, etc.) */
|
|
90
91
|
isProcessing: boolean;
|
|
91
92
|
/** Whether user is currently dragging over the dropzone */
|
|
92
93
|
isDragging: boolean;
|
|
94
|
+
/** Flattened access to files */
|
|
95
|
+
files: ProcessedFile[];
|
|
96
|
+
/** Flattened access to source name */
|
|
97
|
+
sourceName: string;
|
|
98
|
+
/** Flattened access to status */
|
|
99
|
+
status: {
|
|
100
|
+
title: string;
|
|
101
|
+
details: string;
|
|
102
|
+
} | null;
|
|
93
103
|
/** Get props to spread on dropzone element (handles drag & drop) */
|
|
94
104
|
getDropzoneProps: () => {
|
|
95
105
|
onDragOver: (e: React.DragEvent) => void;
|
|
@@ -115,7 +125,7 @@ interface DropReturn {
|
|
|
115
125
|
/** Clear all files and reset state */
|
|
116
126
|
clearAll: () => void;
|
|
117
127
|
/** Get only valid files ready for upload */
|
|
118
|
-
|
|
128
|
+
validFiles: ProcessedFile[];
|
|
119
129
|
/** Update upload state for a specific file (status, progress, message) */
|
|
120
130
|
updateFileStatus: (fileId: string, state: {
|
|
121
131
|
status: FileStatus;
|
|
@@ -144,7 +154,6 @@ declare function useDrop(options: DropOptions): DropReturn;
|
|
|
144
154
|
* Unified file processing utilities
|
|
145
155
|
* Converts Files directly to ProcessedFiles
|
|
146
156
|
*/
|
|
147
|
-
|
|
148
157
|
/**
|
|
149
158
|
* Format file size to human-readable string
|
|
150
159
|
* Re-exported from Ship SDK for convenience
|
|
@@ -166,16 +175,16 @@ declare function createProcessedFile(file: File, options?: {
|
|
|
166
175
|
/** Custom path (defaults to webkitRelativePath or file.name) */
|
|
167
176
|
path?: string;
|
|
168
177
|
}): Promise<ProcessedFile>;
|
|
169
|
-
/**
|
|
170
|
-
* Get only the valid files (status: READY) from a list
|
|
171
|
-
* Re-exported from Ship SDK for convenience
|
|
172
|
-
*/
|
|
173
|
-
declare const getValidFiles: (files: ProcessedFile[]) => ProcessedFile[];
|
|
174
178
|
/**
|
|
175
179
|
* Strip common directory prefix from file paths
|
|
176
180
|
* Only strips if ALL files share the same prefix
|
|
177
181
|
*/
|
|
178
182
|
declare function stripCommonPrefix(files: ProcessedFile[]): ProcessedFile[];
|
|
183
|
+
/**
|
|
184
|
+
* Recursively traverse FileSystemEntry from drag & drop to collect all files
|
|
185
|
+
* Properly sets webkitRelativePath to preserve folder structure
|
|
186
|
+
*/
|
|
187
|
+
declare function traverseFileTree(entry: FileSystemEntry, files: File[], currentPath?: string): Promise<void>;
|
|
179
188
|
|
|
180
189
|
interface ZipExtractionResult {
|
|
181
190
|
/** Extracted files as regular File objects */
|
|
@@ -203,4 +212,4 @@ declare function normalizePath(path: string): string;
|
|
|
203
212
|
*/
|
|
204
213
|
declare function isZipFile(file: File): boolean;
|
|
205
214
|
|
|
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,
|
|
215
|
+
export { type ClientError, type DropOptions, type DropReturn, type DropState, type DropStateValue, type DropStatus, FILE_STATUSES, type FileStatus, type ProcessedFile, type ZipExtractionResult, createProcessedFile, extractZipToFiles, formatFileSize, isZipFile, normalizePath, stripCommonPrefix, traverseFileTree, useDrop };
|
package/dist/index.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ type DropStateValue = 'idle' | 'dragging' | 'processing' | 'ready' | 'error';
|
|
|
62
62
|
interface DropStatus {
|
|
63
63
|
title: string;
|
|
64
64
|
details: string;
|
|
65
|
+
errors?: string[];
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
68
|
* State machine state for the drop hook
|
|
@@ -84,12 +85,21 @@ interface DropOptions {
|
|
|
84
85
|
stripPrefix?: boolean;
|
|
85
86
|
}
|
|
86
87
|
interface DropReturn {
|
|
87
|
-
/** Current
|
|
88
|
-
|
|
88
|
+
/** Current phase of the state machine */
|
|
89
|
+
phase: DropStateValue;
|
|
89
90
|
/** Whether currently processing files (ZIP extraction, etc.) */
|
|
90
91
|
isProcessing: boolean;
|
|
91
92
|
/** Whether user is currently dragging over the dropzone */
|
|
92
93
|
isDragging: boolean;
|
|
94
|
+
/** Flattened access to files */
|
|
95
|
+
files: ProcessedFile[];
|
|
96
|
+
/** Flattened access to source name */
|
|
97
|
+
sourceName: string;
|
|
98
|
+
/** Flattened access to status */
|
|
99
|
+
status: {
|
|
100
|
+
title: string;
|
|
101
|
+
details: string;
|
|
102
|
+
} | null;
|
|
93
103
|
/** Get props to spread on dropzone element (handles drag & drop) */
|
|
94
104
|
getDropzoneProps: () => {
|
|
95
105
|
onDragOver: (e: React.DragEvent) => void;
|
|
@@ -115,7 +125,7 @@ interface DropReturn {
|
|
|
115
125
|
/** Clear all files and reset state */
|
|
116
126
|
clearAll: () => void;
|
|
117
127
|
/** Get only valid files ready for upload */
|
|
118
|
-
|
|
128
|
+
validFiles: ProcessedFile[];
|
|
119
129
|
/** Update upload state for a specific file (status, progress, message) */
|
|
120
130
|
updateFileStatus: (fileId: string, state: {
|
|
121
131
|
status: FileStatus;
|
|
@@ -144,7 +154,6 @@ declare function useDrop(options: DropOptions): DropReturn;
|
|
|
144
154
|
* Unified file processing utilities
|
|
145
155
|
* Converts Files directly to ProcessedFiles
|
|
146
156
|
*/
|
|
147
|
-
|
|
148
157
|
/**
|
|
149
158
|
* Format file size to human-readable string
|
|
150
159
|
* Re-exported from Ship SDK for convenience
|
|
@@ -166,16 +175,16 @@ declare function createProcessedFile(file: File, options?: {
|
|
|
166
175
|
/** Custom path (defaults to webkitRelativePath or file.name) */
|
|
167
176
|
path?: string;
|
|
168
177
|
}): Promise<ProcessedFile>;
|
|
169
|
-
/**
|
|
170
|
-
* Get only the valid files (status: READY) from a list
|
|
171
|
-
* Re-exported from Ship SDK for convenience
|
|
172
|
-
*/
|
|
173
|
-
declare const getValidFiles: (files: ProcessedFile[]) => ProcessedFile[];
|
|
174
178
|
/**
|
|
175
179
|
* Strip common directory prefix from file paths
|
|
176
180
|
* Only strips if ALL files share the same prefix
|
|
177
181
|
*/
|
|
178
182
|
declare function stripCommonPrefix(files: ProcessedFile[]): ProcessedFile[];
|
|
183
|
+
/**
|
|
184
|
+
* Recursively traverse FileSystemEntry from drag & drop to collect all files
|
|
185
|
+
* Properly sets webkitRelativePath to preserve folder structure
|
|
186
|
+
*/
|
|
187
|
+
declare function traverseFileTree(entry: FileSystemEntry, files: File[], currentPath?: string): Promise<void>;
|
|
179
188
|
|
|
180
189
|
interface ZipExtractionResult {
|
|
181
190
|
/** Extracted files as regular File objects */
|
|
@@ -203,4 +212,4 @@ declare function normalizePath(path: string): string;
|
|
|
203
212
|
*/
|
|
204
213
|
declare function isZipFile(file: File): boolean;
|
|
205
214
|
|
|
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,
|
|
215
|
+
export { type ClientError, type DropOptions, type DropReturn, type DropState, type DropStateValue, type DropStatus, FILE_STATUSES, type FileStatus, type ProcessedFile, type ZipExtractionResult, createProcessedFile, extractZipToFiles, formatFileSize, isZipFile, normalizePath, stripCommonPrefix, traverseFileTree, useDrop };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useRef, useMemo, useCallback } from 'react';
|
|
2
|
-
import { formatFileSize as formatFileSize$1, getValidFiles
|
|
2
|
+
import { formatFileSize as formatFileSize$1, getValidFiles, filterJunk, validateFiles } from '@shipstatic/ship';
|
|
3
3
|
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -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
|
});
|
|
@@ -11811,7 +11811,6 @@ async function createProcessedFile(file, options) {
|
|
|
11811
11811
|
status: FILE_STATUSES.PENDING
|
|
11812
11812
|
};
|
|
11813
11813
|
}
|
|
11814
|
-
var getValidFiles = getValidFiles$1;
|
|
11815
11814
|
function stripCommonPrefix(files) {
|
|
11816
11815
|
if (files.length === 0) return files;
|
|
11817
11816
|
const paths = files.map((f) => f.path);
|
|
@@ -11833,35 +11832,39 @@ function stripCommonPrefix(files) {
|
|
|
11833
11832
|
}));
|
|
11834
11833
|
}
|
|
11835
11834
|
async function traverseFileTree(entry, files, currentPath = "") {
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
const
|
|
11851
|
-
|
|
11852
|
-
|
|
11835
|
+
try {
|
|
11836
|
+
if (entry.isFile) {
|
|
11837
|
+
const file = await new Promise((resolve, reject) => {
|
|
11838
|
+
entry.file(resolve, reject);
|
|
11839
|
+
});
|
|
11840
|
+
const relativePath = currentPath ? `${currentPath}/${file.name}` : file.name;
|
|
11841
|
+
Object.defineProperty(file, "webkitRelativePath", {
|
|
11842
|
+
value: relativePath,
|
|
11843
|
+
writable: false
|
|
11844
|
+
});
|
|
11845
|
+
files.push(file);
|
|
11846
|
+
} else if (entry.isDirectory) {
|
|
11847
|
+
const dirReader = entry.createReader();
|
|
11848
|
+
let allEntries = [];
|
|
11849
|
+
const readEntriesBatch = async () => {
|
|
11850
|
+
const batch = await new Promise(
|
|
11851
|
+
(resolve, reject) => {
|
|
11852
|
+
dirReader.readEntries(resolve, reject);
|
|
11853
|
+
}
|
|
11854
|
+
);
|
|
11855
|
+
if (batch.length > 0) {
|
|
11856
|
+
allEntries = allEntries.concat(batch);
|
|
11857
|
+
await readEntriesBatch();
|
|
11853
11858
|
}
|
|
11854
|
-
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
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);
|
|
11858
11864
|
}
|
|
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
11865
|
}
|
|
11866
|
+
} catch (error) {
|
|
11867
|
+
console.warn(`Error traversing file tree for entry ${entry.name}:`, error);
|
|
11865
11868
|
}
|
|
11866
11869
|
}
|
|
11867
11870
|
function useDrop(options) {
|
|
@@ -11882,6 +11885,7 @@ function useDrop(options) {
|
|
|
11882
11885
|
const inputRef = useRef(null);
|
|
11883
11886
|
const isProcessing = useMemo(() => state.value === "processing", [state.value]);
|
|
11884
11887
|
const isDragging = useMemo(() => state.value === "dragging", [state.value]);
|
|
11888
|
+
const validFiles = useMemo(() => getValidFiles(state.files), [state.files]);
|
|
11885
11889
|
const processFiles = useCallback(async (newFiles) => {
|
|
11886
11890
|
if (isProcessingRef.current) {
|
|
11887
11891
|
console.warn("File processing already in progress. Ignoring duplicate call.");
|
|
@@ -11947,7 +11951,11 @@ function useDrop(options) {
|
|
|
11947
11951
|
value: "error",
|
|
11948
11952
|
files: validation.files,
|
|
11949
11953
|
sourceName: detectedSourceName,
|
|
11950
|
-
status: {
|
|
11954
|
+
status: {
|
|
11955
|
+
title: validation.error.error,
|
|
11956
|
+
details: validation.error.details,
|
|
11957
|
+
errors: validation.error.errors
|
|
11958
|
+
}
|
|
11951
11959
|
});
|
|
11952
11960
|
onValidationError?.(validation.error);
|
|
11953
11961
|
} else if (validation.validFiles.length > 0) {
|
|
@@ -11992,9 +12000,6 @@ function useDrop(options) {
|
|
|
11992
12000
|
setState(initialState);
|
|
11993
12001
|
isProcessingRef.current = false;
|
|
11994
12002
|
}, []);
|
|
11995
|
-
const getValidFilesCallback = useCallback(() => {
|
|
11996
|
-
return getValidFiles(state.files);
|
|
11997
|
-
}, [state.files]);
|
|
11998
12003
|
const updateFileStatus = useCallback((fileId, fileState) => {
|
|
11999
12004
|
setState((prev) => ({
|
|
12000
12005
|
...prev,
|
|
@@ -12027,14 +12032,27 @@ function useDrop(options) {
|
|
|
12027
12032
|
let hasEntries = false;
|
|
12028
12033
|
for (const item of items) {
|
|
12029
12034
|
if (item.kind === "file") {
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
|
|
12036
|
-
|
|
12037
|
-
|
|
12035
|
+
try {
|
|
12036
|
+
const entry = item.webkitGetAsEntry?.();
|
|
12037
|
+
if (entry) {
|
|
12038
|
+
hasEntries = true;
|
|
12039
|
+
await traverseFileTree(
|
|
12040
|
+
entry,
|
|
12041
|
+
files,
|
|
12042
|
+
entry.isDirectory ? entry.name : ""
|
|
12043
|
+
);
|
|
12044
|
+
} else {
|
|
12045
|
+
const file = item.getAsFile();
|
|
12046
|
+
if (file) {
|
|
12047
|
+
files.push(file);
|
|
12048
|
+
}
|
|
12049
|
+
}
|
|
12050
|
+
} catch (error) {
|
|
12051
|
+
console.warn("Error processing drop item:", error);
|
|
12052
|
+
const file = item.getAsFile();
|
|
12053
|
+
if (file) {
|
|
12054
|
+
files.push(file);
|
|
12055
|
+
}
|
|
12038
12056
|
}
|
|
12039
12057
|
}
|
|
12040
12058
|
}
|
|
@@ -12072,10 +12090,14 @@ function useDrop(options) {
|
|
|
12072
12090
|
}), [handleInputChange]);
|
|
12073
12091
|
return {
|
|
12074
12092
|
// State machine
|
|
12075
|
-
state,
|
|
12093
|
+
// state, // REMOVED
|
|
12076
12094
|
// Convenience getters (computed from state)
|
|
12095
|
+
phase: state.value,
|
|
12077
12096
|
isProcessing,
|
|
12078
12097
|
isDragging,
|
|
12098
|
+
files: state.files,
|
|
12099
|
+
sourceName: state.sourceName,
|
|
12100
|
+
status: state.status,
|
|
12079
12101
|
// Primary API: Prop getters
|
|
12080
12102
|
getDropzoneProps,
|
|
12081
12103
|
getInputProps,
|
|
@@ -12084,7 +12106,7 @@ function useDrop(options) {
|
|
|
12084
12106
|
processFiles,
|
|
12085
12107
|
clearAll,
|
|
12086
12108
|
// Helpers
|
|
12087
|
-
|
|
12109
|
+
validFiles,
|
|
12088
12110
|
updateFileStatus
|
|
12089
12111
|
};
|
|
12090
12112
|
}
|
|
@@ -12112,6 +12134,6 @@ mime-db/index.js:
|
|
|
12112
12134
|
*)
|
|
12113
12135
|
*/
|
|
12114
12136
|
|
|
12115
|
-
export { FILE_STATUSES, createProcessedFile, extractZipToFiles, formatFileSize,
|
|
12137
|
+
export { FILE_STATUSES, createProcessedFile, extractZipToFiles, formatFileSize, isZipFile, normalizePath, stripCommonPrefix, traverseFileTree, useDrop };
|
|
12116
12138
|
//# sourceMappingURL=index.js.map
|
|
12117
12139
|
//# sourceMappingURL=index.js.map
|