@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/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 state of the drop hook */
88
- state: DropState;
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
- getValidFiles: () => ProcessedFile[];
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, getValidFiles, isZipFile, normalizePath, stripCommonPrefix, useDrop };
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 state of the drop hook */
88
- state: DropState;
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
- getValidFiles: () => ProcessedFile[];
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, getValidFiles, isZipFile, normalizePath, stripCommonPrefix, useDrop };
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 as getValidFiles$1, filterJunk, validateFiles } from '@shipstatic/ship';
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
- 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);
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
- if (batch.length > 0) {
11856
- allEntries = allEntries.concat(batch);
11857
- await readEntriesBatch();
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: { title: validation.error.error, details: validation.error.details }
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
- const entry = item.webkitGetAsEntry?.();
12031
- if (entry) {
12032
- hasEntries = true;
12033
- await traverseFileTree(
12034
- entry,
12035
- files,
12036
- entry.isDirectory ? entry.name : ""
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
- getValidFiles: getValidFilesCallback,
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, getValidFiles, isZipFile, normalizePath, stripCommonPrefix, useDrop };
12137
+ export { FILE_STATUSES, createProcessedFile, extractZipToFiles, formatFileSize, isZipFile, normalizePath, stripCommonPrefix, traverseFileTree, useDrop };
12116
12138
  //# sourceMappingURL=index.js.map
12117
12139
  //# sourceMappingURL=index.js.map