@shipstatic/drop 2.10.4-beta.6 → 2.10.4-beta.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/dist/index.cjs CHANGED
@@ -1110,7 +1110,7 @@ var initialState = {
1110
1110
  };
1111
1111
  function useDrop({ ship }) {
1112
1112
  const [state, setState] = react.useState(initialState);
1113
- const isProcessingRef = react.useRef(false);
1113
+ const runRef = react.useRef(null);
1114
1114
  const folderInputRef = react.useRef(null);
1115
1115
  const filesInputRef = react.useRef(null);
1116
1116
  const isProcessing = state.phase === "processing";
@@ -1121,24 +1121,36 @@ function useDrop({ ship }) {
1121
1121
  [state.files]
1122
1122
  );
1123
1123
  const getFilesForUpload = react.useCallback(() => validFiles.map((f) => f.file), [validFiles]);
1124
- const processFiles2 = react.useCallback(
1125
- async (newFiles) => {
1126
- if (isProcessingRef.current) {
1124
+ const prepare = react.useCallback(
1125
+ async (collect) => {
1126
+ if (runRef.current) {
1127
1127
  console.warn("File processing already in progress. Ignoring duplicate call.");
1128
1128
  return;
1129
1129
  }
1130
- if (!newFiles || newFiles.length === 0) return;
1131
- isProcessingRef.current = true;
1130
+ const run = new AbortController();
1131
+ runRef.current = run;
1132
1132
  setState({
1133
1133
  ...initialState,
1134
1134
  phase: "processing",
1135
1135
  status: { title: "Processing...", details: "Validating and preparing files." }
1136
1136
  });
1137
1137
  try {
1138
- const outcome = await processFiles(newFiles, {
1139
- limits: await ship.getLimits(),
1140
- onStatus: (status) => setState((prev) => ({ ...prev, status }))
1138
+ const [files, limits] = await Promise.all([
1139
+ collect(),
1140
+ ship.getLimits({ signal: run.signal })
1141
+ ]);
1142
+ if (run.signal.aborted) return;
1143
+ if (files.length === 0) {
1144
+ setState(initialState);
1145
+ return;
1146
+ }
1147
+ const outcome = await processFiles(files, {
1148
+ limits,
1149
+ onStatus: (status) => {
1150
+ if (!run.signal.aborted) setState((prev) => ({ ...prev, status }));
1151
+ }
1141
1152
  });
1153
+ if (run.signal.aborted) return;
1142
1154
  setState({
1143
1155
  phase: outcome.phase,
1144
1156
  isDragging: false,
@@ -1147,15 +1159,33 @@ function useDrop({ ship }) {
1147
1159
  status: outcome.status,
1148
1160
  needsBuild: outcome.needsBuild
1149
1161
  });
1162
+ } catch (error) {
1163
+ if (run.signal.aborted) return;
1164
+ setState({
1165
+ ...initialState,
1166
+ phase: "error",
1167
+ status: {
1168
+ title: "Processing Failed",
1169
+ details: error instanceof Error ? error.message : String(error)
1170
+ }
1171
+ });
1150
1172
  } finally {
1151
- isProcessingRef.current = false;
1173
+ if (runRef.current === run) runRef.current = null;
1152
1174
  }
1153
1175
  },
1154
1176
  [ship]
1155
1177
  );
1178
+ const processFiles2 = react.useCallback(
1179
+ async (newFiles) => {
1180
+ if (!newFiles || newFiles.length === 0) return;
1181
+ await prepare(async () => newFiles);
1182
+ },
1183
+ [prepare]
1184
+ );
1156
1185
  const reset = react.useCallback(() => {
1186
+ runRef.current?.abort();
1187
+ runRef.current = null;
1157
1188
  setState(initialState);
1158
- isProcessingRef.current = false;
1159
1189
  }, []);
1160
1190
  const handleDragOver = react.useCallback((e) => {
1161
1191
  e.preventDefault();
@@ -1190,13 +1220,14 @@ function useDrop({ ship }) {
1190
1220
  if (file) files.push(file);
1191
1221
  }
1192
1222
  }
1193
- await Promise.all(directories.map((d) => traverseFileTree(d.entry, files, d.path)));
1194
- if (files.length === 0 && e.dataTransfer.files.length > 0) {
1195
- files.push(...Array.from(e.dataTransfer.files));
1196
- }
1197
- if (files.length > 0) await processFiles2(files);
1223
+ const plain = Array.from(e.dataTransfer.files);
1224
+ if (directories.length === 0 && files.length === 0 && plain.length === 0) return;
1225
+ await prepare(async () => {
1226
+ await Promise.all(directories.map((d) => traverseFileTree(d.entry, files, d.path)));
1227
+ return files.length > 0 ? files : plain;
1228
+ });
1198
1229
  },
1199
- [processFiles2]
1230
+ [prepare]
1200
1231
  );
1201
1232
  const handleInputChange = react.useCallback(
1202
1233
  (e) => {