@rainbow-oh/yee-c 0.9.2 → 0.10.0

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.
Files changed (109) hide show
  1. package/dist/cjs/Input/style/index.less +1 -0
  2. package/dist/cjs/Tabs/demo/overflow-center.d.ts +3 -0
  3. package/dist/cjs/Tabs/demo/overflow-center.js +54 -0
  4. package/dist/cjs/Tabs/hooks/useNavListMove.d.ts +2 -1
  5. package/dist/cjs/Tabs/hooks/useNavListMove.js +51 -16
  6. package/dist/cjs/Tabs/hooks/useTabScroll.d.ts +1 -0
  7. package/dist/cjs/Tabs/hooks/useTabScroll.js +5 -1
  8. package/dist/cjs/Tabs/interface.d.ts +9 -0
  9. package/dist/cjs/Tabs/style/index.less +5 -0
  10. package/dist/cjs/Tabs/tab-header/index.d.ts +1 -0
  11. package/dist/cjs/Tabs/tab-header/index.js +9 -2
  12. package/dist/cjs/Tabs/tabs.js +4 -1
  13. package/dist/cjs/Upload/demo/auto-upload.d.ts +3 -0
  14. package/dist/cjs/Upload/demo/auto-upload.js +65 -0
  15. package/dist/cjs/Upload/demo/basic.js +5 -10
  16. package/dist/cjs/Upload/demo/controlled.js +4 -4
  17. package/dist/cjs/Upload/demo/pictureWall.js +14 -13
  18. package/dist/cjs/Upload/dragger.d.ts +2 -1
  19. package/dist/cjs/Upload/dragger.js +32 -21
  20. package/dist/cjs/Upload/index.d.ts +1 -1
  21. package/dist/cjs/Upload/interface.d.ts +67 -120
  22. package/dist/cjs/Upload/style/index.less +40 -13
  23. package/dist/cjs/Upload/upload.d.ts +2 -2
  24. package/dist/cjs/Upload/upload.js +435 -185
  25. package/dist/cjs/Upload/uploaded-list/index.d.ts +2 -1
  26. package/dist/cjs/Upload/uploaded-list/index.js +6 -3
  27. package/dist/cjs/Upload/uploaded-list/uploaded-item.d.ts +6 -3
  28. package/dist/cjs/Upload/uploaded-list/uploaded-item.js +127 -138
  29. package/dist/cjs/style/size.css +1 -1
  30. package/dist/cjs/style/themes.css +1 -1
  31. package/dist/cjs/style/variables.css +2 -2
  32. package/dist/cjs/utils/ax/core.d.ts +3 -1
  33. package/dist/cjs/utils/ax/core.js +24 -37
  34. package/dist/cjs/utils/ax/index.d.ts +3 -1
  35. package/dist/cjs/utils/folder-scanner.d.ts +1 -1
  36. package/dist/cjs/utils/folder-scanner.js +43 -34
  37. package/dist/cjs/version.d.ts +1 -1
  38. package/dist/cjs/version.js +1 -1
  39. package/dist/esm/Input/style/index.less +1 -0
  40. package/dist/esm/Tabs/demo/overflow-center.d.ts +3 -0
  41. package/dist/esm/Tabs/demo/overflow-center.js +61 -0
  42. package/dist/esm/Tabs/hooks/useNavListMove.d.ts +2 -1
  43. package/dist/esm/Tabs/hooks/useNavListMove.js +62 -25
  44. package/dist/esm/Tabs/hooks/useTabScroll.d.ts +1 -0
  45. package/dist/esm/Tabs/hooks/useTabScroll.js +9 -0
  46. package/dist/esm/Tabs/interface.d.ts +9 -0
  47. package/dist/esm/Tabs/style/index.less +5 -0
  48. package/dist/esm/Tabs/tab-header/index.d.ts +1 -0
  49. package/dist/esm/Tabs/tab-header/index.js +13 -2
  50. package/dist/esm/Tabs/tabs.js +4 -2
  51. package/dist/esm/Upload/demo/auto-upload.d.ts +3 -0
  52. package/dist/esm/Upload/demo/auto-upload.js +42 -0
  53. package/dist/esm/Upload/demo/basic.js +5 -11
  54. package/dist/esm/Upload/demo/controlled.js +8 -6
  55. package/dist/esm/Upload/demo/pictureWall.js +17 -14
  56. package/dist/esm/Upload/dragger.d.ts +2 -1
  57. package/dist/esm/Upload/dragger.js +10 -5
  58. package/dist/esm/Upload/index.d.ts +1 -1
  59. package/dist/esm/Upload/interface.d.ts +67 -120
  60. package/dist/esm/Upload/style/index.less +40 -13
  61. package/dist/esm/Upload/upload.d.ts +2 -2
  62. package/dist/esm/Upload/upload.js +573 -271
  63. package/dist/esm/Upload/uploaded-list/index.d.ts +2 -1
  64. package/dist/esm/Upload/uploaded-list/index.js +9 -4
  65. package/dist/esm/Upload/uploaded-list/uploaded-item.d.ts +6 -3
  66. package/dist/esm/Upload/uploaded-list/uploaded-item.js +145 -150
  67. package/dist/esm/style/size.css +1 -1
  68. package/dist/esm/style/themes.css +1 -1
  69. package/dist/esm/style/variables.css +2 -2
  70. package/dist/esm/utils/ax/core.d.ts +3 -1
  71. package/dist/esm/utils/ax/core.js +32 -40
  72. package/dist/esm/utils/ax/index.d.ts +3 -1
  73. package/dist/esm/utils/folder-scanner.d.ts +1 -1
  74. package/dist/esm/utils/folder-scanner.js +76 -75
  75. package/dist/esm/version.d.ts +1 -1
  76. package/dist/esm/version.js +1 -1
  77. package/dist/umd/yee-c.min.css +2 -2
  78. package/dist/umd/yee-c.min.js +1 -1
  79. package/package.json +1 -1
  80. package/src/Input/style/index.less +1 -0
  81. package/src/Tabs/demo/overflow-center.tsx +35 -0
  82. package/src/Tabs/hooks/useNavListMove.ts +60 -18
  83. package/src/Tabs/hooks/useTabScroll.ts +7 -1
  84. package/src/Tabs/index.en-US.md +33 -31
  85. package/src/Tabs/index.zh-CN.md +33 -31
  86. package/src/Tabs/interface.ts +9 -0
  87. package/src/Tabs/style/index.less +5 -0
  88. package/src/Tabs/tab-header/index.tsx +12 -2
  89. package/src/Tabs/tabs.tsx +2 -0
  90. package/src/Upload/demo/auto-upload.tsx +35 -0
  91. package/src/Upload/demo/basic.tsx +7 -11
  92. package/src/Upload/demo/controlled.tsx +12 -8
  93. package/src/Upload/demo/directory.tsx +3 -4
  94. package/src/Upload/demo/drag.tsx +5 -12
  95. package/src/Upload/demo/multiple.tsx +3 -4
  96. package/src/Upload/demo/pictureWall.tsx +22 -21
  97. package/src/Upload/dragger.tsx +47 -34
  98. package/src/Upload/index.en-US.md +63 -43
  99. package/src/Upload/index.ts +8 -1
  100. package/src/Upload/index.zh-CN.md +62 -42
  101. package/src/Upload/interface.ts +68 -120
  102. package/src/Upload/style/index.less +40 -13
  103. package/src/Upload/upload.tsx +546 -215
  104. package/src/Upload/uploaded-list/index.tsx +9 -5
  105. package/src/Upload/uploaded-list/uploaded-item.tsx +199 -228
  106. package/src/style/size.css +1 -1
  107. package/src/utils/ax/core.ts +28 -41
  108. package/src/utils/folder-scanner.ts +51 -37
  109. package/src/version.ts +1 -1
@@ -87,26 +87,89 @@ var import_react = __toESM(require("react"));
87
87
  var import_uuid = require("uuid");
88
88
  var import_Button = __toESM(require("../Button"));
89
89
  var import_Config_Provider = require("../Config-Provider");
90
- var import_mergeContextToProps = __toESM(require("../utils/mergeContextToProps"));
91
- var import_uploaded_list = __toESM(require("./uploaded-list/index"));
92
90
  var import_useMergedState = __toESM(require("../hooks/useMergedState"));
93
91
  var import_ax = __toESM(require("../utils/ax"));
94
92
  var import_folder_scanner = __toESM(require("../utils/folder-scanner"));
93
+ var import_mergeContextToProps = __toESM(require("../utils/mergeContextToProps"));
95
94
  var import_style = require("./style/index.less");
95
+ var import_uploaded_list = __toESM(require("./uploaded-list/index"));
96
+ var getFileExtension = (fileName) => {
97
+ const dotIndex = fileName.lastIndexOf(".");
98
+ return dotIndex > -1 ? fileName.slice(dotIndex + 1).toLowerCase() : "";
99
+ };
96
100
  var wrapFile = (file) => {
97
101
  return {
98
102
  uid: (0, import_uuid.v4)(),
99
103
  name: file.name,
100
104
  size: file.size,
101
- type: typeof (file == null ? void 0 : file.name) === "string" ? file.name.split(".")[1] : "",
105
+ type: file.type || getFileExtension(file.name),
102
106
  percent: 0,
103
107
  status: "ready",
104
108
  raw: file
105
109
  };
106
110
  };
111
+ var isSameFile = (left, right) => {
112
+ if (left.uid && right.uid) {
113
+ return left.uid === right.uid;
114
+ }
115
+ return left === right;
116
+ };
117
+ var matchesAccept = (file, accept) => {
118
+ if (!accept) {
119
+ return true;
120
+ }
121
+ const fileName = file.name.toLowerCase();
122
+ const mimeType = file.type.toLowerCase();
123
+ return accept.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean).some((rule) => {
124
+ if (rule.startsWith(".")) {
125
+ return fileName.endsWith(rule);
126
+ }
127
+ if (rule.endsWith("/*")) {
128
+ return mimeType.startsWith(rule.slice(0, -1));
129
+ }
130
+ return mimeType === rule;
131
+ });
132
+ };
133
+ var describeErrorDetail = (detail) => {
134
+ var _a;
135
+ if (typeof detail === "string" && detail) {
136
+ return detail;
137
+ }
138
+ try {
139
+ const text = (_a = JSON.stringify(detail)) != null ? _a : "";
140
+ return text.length > 200 ? `${text.slice(0, 200)}…` : text;
141
+ } catch (e) {
142
+ return String(detail);
143
+ }
144
+ };
145
+ var toError = (error) => {
146
+ if (error instanceof Error) {
147
+ return error;
148
+ }
149
+ if (typeof error === "object" && error !== null && "error" in error) {
150
+ const detail = error.error;
151
+ if (detail instanceof Error) {
152
+ return detail;
153
+ }
154
+ if (detail !== null && detail !== void 0) {
155
+ const message = describeErrorDetail(detail);
156
+ if (message) {
157
+ return new Error(message);
158
+ }
159
+ }
160
+ }
161
+ return new Error(typeof error === "string" ? error : "Upload failed");
162
+ };
163
+ var isAbortRejection = (error) => typeof error === "object" && error !== null && error.status === "abort";
164
+ var getAbort = (request) => {
165
+ if (typeof request === "function") {
166
+ return request;
167
+ }
168
+ return request == null ? void 0 : request.abort;
169
+ };
107
170
  var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
108
- const { upload } = (0, import_react.useContext)(import_Config_Provider.GlobalContext);
109
- const props = (0, import_mergeContextToProps.default)(baseprops, upload);
171
+ const { upload: uploadConfig } = (0, import_react.useContext)(import_Config_Provider.GlobalContext);
172
+ const props = (0, import_mergeContextToProps.default)(baseprops, uploadConfig);
110
173
  const _a = props, {
111
174
  prefixCls = "yee-upload",
112
175
  name = "file",
@@ -127,6 +190,7 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
127
190
  accept,
128
191
  showUploadList = true,
129
192
  progress = true,
193
+ autoUpload = true,
130
194
  maxFileSize,
131
195
  maxCount,
132
196
  customRequest,
@@ -155,6 +219,7 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
155
219
  "accept",
156
220
  "showUploadList",
157
221
  "progress",
222
+ "autoUpload",
158
223
  "maxFileSize",
159
224
  "maxCount",
160
225
  "customRequest",
@@ -165,246 +230,430 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
165
230
  "itemRender"
166
231
  ]);
167
232
  const inputRef = (0, import_react.useRef)(null);
233
+ const rootRef = (0, import_react.useRef)(null);
234
+ const activeRequestsRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
235
+ const pendingPreparationsRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
236
+ const mountedRef = (0, import_react.useRef)(true);
168
237
  const [dragState, setDragState] = (0, import_react.useState)(null);
169
238
  const [mergedFileList, setMergedFileList] = (0, import_useMergedState.default)([], {
170
239
  value: propsFileList,
171
240
  defaultValue: defaultFileList
172
241
  });
173
- let acceptDirectory = {};
174
- if (directory) {
175
- acceptDirectory = {
176
- webkitdirectory: "",
177
- directory: "",
178
- multiple: ""
242
+ const fileListRef = (0, import_react.useRef)(mergedFileList);
243
+ fileListRef.current = mergedFileList;
244
+ (0, import_react.useEffect)(() => {
245
+ return () => {
246
+ mountedRef.current = false;
247
+ pendingPreparationsRef.current.clear();
248
+ const activeRequests = Array.from(activeRequestsRef.current.values());
249
+ activeRequestsRef.current.clear();
250
+ activeRequests.forEach(({ abort }) => abort == null ? void 0 : abort());
179
251
  };
180
- }
181
- const updateFileList = (file) => {
182
- setMergedFileList((state) => {
183
- return state.map((item) => {
184
- if (item.uid === file.uid) {
185
- return file;
186
- }
187
- return item;
188
- });
189
- });
252
+ }, []);
253
+ const setFileList = (nextFileList) => {
254
+ fileListRef.current = nextFileList;
255
+ setMergedFileList(nextFileList);
190
256
  };
191
- const postFile = (file) => {
192
- const formData = new FormData();
193
- formData.append(name, file.raw);
194
- if (data) {
195
- const extraData = typeof data === "function" ? data(file.raw) : data;
196
- Object.keys(extraData).forEach((key) => {
197
- formData.append(key, extraData[key]);
198
- });
257
+ const emitChange = (file, nextFileList, event) => {
258
+ setFileList(nextFileList);
259
+ onChange == null ? void 0 : onChange({ file, fileList: nextFileList, event });
260
+ };
261
+ const appendFile = (file, event) => {
262
+ const nextFileList = [...fileListRef.current, file];
263
+ emitChange(file, nextFileList, event);
264
+ return file;
265
+ };
266
+ const replaceFile = (target, replacement, event) => {
267
+ const index = fileListRef.current.findIndex(
268
+ (item) => isSameFile(item, target)
269
+ );
270
+ if (index < 0) {
271
+ return void 0;
272
+ }
273
+ const nextFileList = [...fileListRef.current];
274
+ nextFileList[index] = replacement;
275
+ emitChange(replacement, nextFileList, event);
276
+ return replacement;
277
+ };
278
+ const updateFile = (target, patch, event) => {
279
+ const current = fileListRef.current.find(
280
+ (item) => isSameFile(item, target)
281
+ );
282
+ if (!current) {
283
+ return void 0;
284
+ }
285
+ return replaceFile(target, __spreadValues(__spreadValues({}, current), patch), event);
286
+ };
287
+ const abortRequest = (file) => {
288
+ var _a2;
289
+ if (!file.uid) {
290
+ return;
291
+ }
292
+ const activeRequest = activeRequestsRef.current.get(file.uid);
293
+ if (activeRequest) {
294
+ activeRequestsRef.current.delete(file.uid);
295
+ (_a2 = activeRequest.abort) == null ? void 0 : _a2.call(activeRequest);
296
+ }
297
+ };
298
+ const postFile = (sourceFile) => {
299
+ let file = sourceFile;
300
+ if (!file.uid) {
301
+ const withUid = __spreadProps(__spreadValues({}, file), { uid: (0, import_uuid.v4)() });
302
+ file = replaceFile(file, withUid) || withUid;
303
+ }
304
+ const requestKey = file.uid;
305
+ abortRequest(file);
306
+ const token = Symbol(requestKey);
307
+ activeRequestsRef.current.set(requestKey, { token });
308
+ const isActive = () => {
309
+ var _a2;
310
+ return ((_a2 = activeRequestsRef.current.get(requestKey)) == null ? void 0 : _a2.token) === token;
311
+ };
312
+ const finish = () => {
313
+ if (isActive()) {
314
+ activeRequestsRef.current.delete(requestKey);
315
+ }
316
+ };
317
+ const updateIfActive = (patch, event) => {
318
+ if (!isActive()) {
319
+ return void 0;
320
+ }
321
+ return updateFile(file, patch, event);
322
+ };
323
+ const fail = (error) => {
324
+ if (isAbortRejection(error)) {
325
+ updateIfActive({ status: "ready", percent: 0 });
326
+ finish();
327
+ return;
328
+ }
329
+ const normalizedError = toError(error);
330
+ updateIfActive({ status: "error", error: normalizedError }, error);
331
+ finish();
332
+ };
333
+ updateIfActive({ status: "uploading", percent: 0, error: void 0 });
334
+ if (!file.raw) {
335
+ fail(new Error(`File ${file.name} has no source file to upload`));
336
+ return;
199
337
  }
200
- const url = typeof action === "function" ? action() : action;
201
338
  if (customRequest) {
202
- customRequest({
203
- file: file.raw,
204
- onProgress: (percent) => {
205
- const current = __spreadProps(__spreadValues({}, file), { status: "uploading", percent });
206
- updateFileList(current);
207
- onChange == null ? void 0 : onChange({
208
- file: current,
209
- fileList: mergedFileList,
210
- event: { percent }
211
- });
212
- },
213
- onError: (error) => {
214
- const current = __spreadProps(__spreadValues({}, file), { status: "error", error });
215
- updateFileList(current);
216
- onChange == null ? void 0 : onChange({
217
- file: current,
218
- fileList: mergedFileList,
219
- event: error
220
- });
221
- },
222
- onSuccess: (response) => {
223
- const current = __spreadProps(__spreadValues({}, file), { status: "success", response });
224
- updateFileList(current);
225
- onChange == null ? void 0 : onChange({
226
- file: current,
227
- fileList: mergedFileList,
228
- event: response
229
- });
339
+ try {
340
+ const request = customRequest({
341
+ file: file.raw,
342
+ onProgress: (percent) => {
343
+ const normalizedPercent = Math.min(100, Math.max(0, percent));
344
+ updateIfActive(
345
+ { status: "uploading", percent: normalizedPercent },
346
+ { percent: normalizedPercent }
347
+ );
348
+ },
349
+ onError: fail,
350
+ onSuccess: (response) => {
351
+ updateIfActive(
352
+ {
353
+ status: "success",
354
+ percent: 100,
355
+ response,
356
+ error: void 0
357
+ },
358
+ response
359
+ );
360
+ finish();
361
+ }
362
+ });
363
+ const activeRequest = activeRequestsRef.current.get(requestKey);
364
+ if ((activeRequest == null ? void 0 : activeRequest.token) === token) {
365
+ activeRequest.abort = getAbort(request);
230
366
  }
231
- });
367
+ } catch (error) {
368
+ fail(error);
369
+ }
232
370
  return;
233
371
  }
234
- import_ax.default.post(url, formData, {
235
- withCredentials,
236
- headers: __spreadValues({}, headers),
237
- onUploadProgress: (e) => {
238
- const percentage = parseInt(e.loaded / e.total * 100 + "");
239
- let current;
240
- if (percentage < 100) {
241
- current = __spreadProps(__spreadValues({}, file), {
242
- status: "uploading",
243
- percent: percentage
244
- });
245
- } else {
246
- current = __spreadProps(__spreadValues({}, file), { status: "success", percent: 100 });
247
- }
248
- updateFileList(current);
249
- onChange == null ? void 0 : onChange({
250
- file: current,
251
- fileList: mergedFileList,
252
- event: e
372
+ try {
373
+ const url = typeof action === "function" ? action() : action;
374
+ if (!url) {
375
+ throw new Error(
376
+ "Upload action is required when customRequest is not set"
377
+ );
378
+ }
379
+ const formData = new FormData();
380
+ formData.append(name, file.raw);
381
+ if (data) {
382
+ const extraData = typeof data === "function" ? data(file.raw) : data;
383
+ Object.keys(extraData).forEach((key) => {
384
+ formData.append(key, extraData[key]);
253
385
  });
254
386
  }
255
- }).then((res) => {
256
- const current = __spreadProps(__spreadValues({}, file), { status: "success", response: res });
257
- updateFileList(current);
258
- onChange == null ? void 0 : onChange({
259
- file: current,
260
- fileList: mergedFileList,
261
- event: res
262
- });
263
- }).catch((err) => {
264
- const current = __spreadProps(__spreadValues({}, file), { status: "error", error: err });
265
- updateFileList(current);
266
- onChange == null ? void 0 : onChange({
267
- file: current,
268
- fileList: mergedFileList,
269
- event: err
387
+ const request = import_ax.default.post(url, formData, {
388
+ withCredentials,
389
+ headers: __spreadValues({}, headers),
390
+ onUploadProgress: (event) => {
391
+ const percentage = event.total ? Math.round(event.loaded / event.total * 100) : 0;
392
+ updateIfActive({ status: "uploading", percent: percentage }, event);
393
+ }
270
394
  });
271
- });
272
- };
273
- const post = (file) => {
274
- setMergedFileList((state) => [...state, file]);
275
- postFile(file);
395
+ const activeRequest = activeRequestsRef.current.get(requestKey);
396
+ if ((activeRequest == null ? void 0 : activeRequest.token) === token) {
397
+ activeRequest.abort = request.abort;
398
+ }
399
+ request.then((response) => {
400
+ updateIfActive(
401
+ {
402
+ status: "success",
403
+ percent: 100,
404
+ response,
405
+ error: void 0
406
+ },
407
+ response
408
+ );
409
+ finish();
410
+ }).catch(fail);
411
+ } catch (error) {
412
+ fail(error);
413
+ }
276
414
  };
277
415
  const isValidFile = (file) => {
278
416
  if (maxFileSize && file.size > maxFileSize) {
279
417
  console.warn(`File ${file.name} exceeds maximum size limit`);
280
418
  return false;
281
419
  }
282
- if (maxCount && mergedFileList.length >= maxCount) {
283
- console.warn(`Maximum file count (${maxCount}) exceeded`);
420
+ if (!matchesAccept(file, accept)) {
421
+ console.warn(`File ${file.name} does not match accepted file types`);
284
422
  return false;
285
423
  }
286
424
  return true;
287
425
  };
288
- const uploadFiles = (files, e) => {
289
- const postFiles = Array.from(files);
290
- postFiles.forEach((file) => {
291
- if (!isValidFile(file)) {
426
+ const prepareFile = (file, wrapped, postFiles, preparationToken, event) => __async(void 0, null, function* () {
427
+ const preparationKey = wrapped.uid;
428
+ const isActive = () => mountedRef.current && pendingPreparationsRef.current.get(preparationKey) === preparationToken && fileListRef.current.some((item) => isSameFile(item, wrapped));
429
+ const finish = () => {
430
+ if (pendingPreparationsRef.current.get(preparationKey) === preparationToken) {
431
+ pendingPreparationsRef.current.delete(preparationKey);
432
+ }
433
+ };
434
+ try {
435
+ const result = beforeUpload ? yield Promise.resolve(beforeUpload(file, postFiles)) : true;
436
+ if (!isActive()) {
437
+ finish();
292
438
  return;
293
439
  }
294
- const wrapped = wrapFile(file);
295
- onChange == null ? void 0 : onChange({
296
- file: wrapped,
297
- fileList: mergedFileList,
298
- event: e
299
- });
300
- if (beforeUpload) {
301
- const res = beforeUpload(file, postFiles);
302
- if (res && res instanceof Promise) {
303
- res.then((progress2) => {
304
- if (progress2 === false) {
305
- return;
306
- }
307
- post(typeof progress2 === "object" ? wrapFile(progress2) : wrapped);
308
- });
309
- } else if (res !== false) {
310
- post(wrapped);
440
+ if (result === false) {
441
+ setFileList(
442
+ fileListRef.current.filter((item) => !isSameFile(item, wrapped))
443
+ );
444
+ finish();
445
+ return;
446
+ }
447
+ let nextFile = wrapped;
448
+ if (result instanceof File) {
449
+ nextFile = __spreadProps(__spreadValues({}, wrapFile(result)), { uid: wrapped.uid });
450
+ if (!replaceFile(wrapped, nextFile, event)) {
451
+ finish();
452
+ return;
311
453
  }
312
- } else {
313
- post(wrapped);
314
454
  }
455
+ finish();
456
+ postFile(nextFile);
457
+ } catch (error) {
458
+ if (isActive()) {
459
+ updateFile(wrapped, { status: "error", error: toError(error) }, error);
460
+ }
461
+ finish();
462
+ }
463
+ });
464
+ const uploadFiles = (files, event) => {
465
+ const selectedFiles = Array.from(files);
466
+ const filesAllowedByMultiple = multiple || directory ? selectedFiles : selectedFiles.slice(0, 1);
467
+ const validFiles = filesAllowedByMultiple.filter(isValidFile);
468
+ const remainingCount = typeof maxCount === "number" ? Math.max(0, maxCount - fileListRef.current.length) : validFiles.length;
469
+ const postFiles = validFiles.slice(0, remainingCount);
470
+ if (postFiles.length < validFiles.length) {
471
+ console.warn(`Maximum file count (${maxCount}) exceeded`);
472
+ }
473
+ postFiles.forEach((file) => {
474
+ const wrapped = appendFile(wrapFile(file), event);
475
+ if (!autoUpload) {
476
+ return;
477
+ }
478
+ const preparationToken = Symbol(wrapped.uid);
479
+ pendingPreparationsRef.current.set(
480
+ wrapped.uid,
481
+ preparationToken
482
+ );
483
+ void prepareFile(file, wrapped, postFiles, preparationToken, event);
315
484
  });
316
485
  };
317
- const handleChange = (e) => {
318
- const files = e.target.files;
319
- if (!files)
486
+ const upload = (file) => {
487
+ const requested = file === void 0 ? fileListRef.current : Array.isArray(file) ? file : [file];
488
+ const readyFiles = requested.filter((item) => item.status === "ready");
489
+ readyFiles.forEach((item) => {
490
+ var _a2;
491
+ let target = item;
492
+ if (!target.uid) {
493
+ target = (_a2 = replaceFile(item, __spreadProps(__spreadValues({}, item), { uid: (0, import_uuid.v4)() }))) != null ? _a2 : item;
494
+ }
495
+ if (!target.raw) {
496
+ updateFile(target, {
497
+ status: "error",
498
+ error: new Error(`File ${target.name} has no source file to upload`)
499
+ });
500
+ return;
501
+ }
502
+ const preparationToken = Symbol(target.uid);
503
+ pendingPreparationsRef.current.set(
504
+ target.uid,
505
+ preparationToken
506
+ );
507
+ void prepareFile(
508
+ target.raw,
509
+ target,
510
+ readyFiles.map((ready) => ready.raw).filter((raw) => raw instanceof File),
511
+ preparationToken
512
+ );
513
+ });
514
+ };
515
+ (0, import_react.useImperativeHandle)(
516
+ ref,
517
+ () => {
518
+ var _a2;
519
+ return Object.assign((_a2 = rootRef.current) != null ? _a2 : document.createElement("div"), {
520
+ upload
521
+ });
522
+ },
523
+ [upload]
524
+ );
525
+ const handleChange = (event) => {
526
+ const files = event.target.files;
527
+ if (!files) {
320
528
  return;
321
- uploadFiles(files, e);
322
- if (inputRef.current) {
323
- inputRef.current.value = "";
324
529
  }
530
+ uploadFiles(files, event);
531
+ event.target.value = "";
325
532
  };
326
- const handleClick = () => {
327
- var _a2;
533
+ const handleDragOver = (event) => {
534
+ event.preventDefault();
328
535
  if (!disabled) {
329
- (_a2 = inputRef.current) == null ? void 0 : _a2.click();
536
+ setDragState("dragover");
330
537
  }
331
538
  };
332
- const handleDragOver = (e) => {
333
- e.preventDefault();
334
- if (disabled)
335
- return;
336
- setDragState("dragover");
337
- };
338
- const handleDragLeave = (e) => {
339
- e.preventDefault();
539
+ const handleDragLeave = (event) => {
540
+ event.preventDefault();
340
541
  setDragState(null);
341
542
  };
342
- const handleDrop = (e) => __async(void 0, null, function* () {
343
- e.preventDefault();
344
- if (disabled)
543
+ const handleDrop = (event) => __async(void 0, null, function* () {
544
+ event.preventDefault();
545
+ if (disabled) {
345
546
  return;
547
+ }
346
548
  setDragState("drop");
347
- const { files, items } = e.dataTransfer;
348
- if (files.length === 1) {
349
- const item = items[0].webkitGetAsEntry();
350
- if (item == null ? void 0 : item.isDirectory) {
351
- const folderFiles = yield (0, import_folder_scanner.default)(item, []);
352
- uploadFiles(folderFiles, e);
353
- } else if (item == null ? void 0 : item.isFile) {
354
- uploadFiles(files, e);
549
+ try {
550
+ const entries = Array.from(event.dataTransfer.items).map((item) => {
551
+ var _a2;
552
+ return (_a2 = item.webkitGetAsEntry) == null ? void 0 : _a2.call(item);
553
+ }).filter(
554
+ (entry) => entry !== null && entry !== void 0
555
+ );
556
+ if (entries.some((entry) => entry.isDirectory)) {
557
+ const nestedFiles = yield Promise.all(
558
+ entries.map((entry) => (0, import_folder_scanner.default)(entry, []))
559
+ );
560
+ uploadFiles(nestedFiles.flat(), event);
561
+ } else {
562
+ uploadFiles(event.dataTransfer.files, event);
563
+ }
564
+ } catch (error) {
565
+ console.warn("Failed to scan dropped files", error);
566
+ } finally {
567
+ setDragState(null);
568
+ }
569
+ });
570
+ const handleRemove = (file) => __async(void 0, null, function* () {
571
+ if (file.uid) {
572
+ pendingPreparationsRef.current.delete(file.uid);
573
+ }
574
+ try {
575
+ const shouldRemove = onRemove ? yield Promise.resolve(onRemove(file)) : true;
576
+ if (shouldRemove === false) {
577
+ return;
355
578
  }
356
- } else if (files.length > 1) {
357
- uploadFiles(files, e);
579
+ abortRequest(file);
580
+ setFileList(
581
+ fileListRef.current.filter((item) => !isSameFile(item, file))
582
+ );
583
+ } catch (error) {
584
+ console.warn(`Failed to remove file ${file.name}`, error);
358
585
  }
359
586
  });
587
+ const handleReUpload = (file) => {
588
+ if (file.uid) {
589
+ pendingPreparationsRef.current.delete(file.uid);
590
+ }
591
+ abortRequest(file);
592
+ const nextFile = updateFile(file, {
593
+ uid: file.uid || (0, import_uuid.v4)(),
594
+ status: "ready",
595
+ percent: 0,
596
+ error: void 0,
597
+ response: void 0
598
+ });
599
+ if (nextFile) {
600
+ postFile(nextFile);
601
+ }
602
+ };
603
+ const handlePreview = (file) => {
604
+ if (onPreview) {
605
+ onPreview(file);
606
+ return;
607
+ }
608
+ if (file.url) {
609
+ window.open(file.url, "_blank", "noopener,noreferrer");
610
+ return;
611
+ }
612
+ if (!file.raw) {
613
+ return;
614
+ }
615
+ const url = URL.createObjectURL(file.raw);
616
+ const previewWindow = window.open(url, "_blank");
617
+ if (!previewWindow) {
618
+ URL.revokeObjectURL(url);
619
+ return;
620
+ }
621
+ const cleanup = () => URL.revokeObjectURL(url);
622
+ previewWindow.addEventListener("load", cleanup, { once: true });
623
+ window.setTimeout(cleanup, 6e4);
624
+ };
360
625
  const renderUploadTrigger = () => {
626
+ const acceptDirectory = directory ? { webkitdirectory: "", directory: "" } : {};
361
627
  return /* @__PURE__ */ import_react.default.createElement(
362
628
  "span",
363
629
  {
364
630
  className: (0, import_clsx.default)(`${prefixCls}-input`, {
365
631
  [`${prefixCls}-input-disabled`]: disabled
366
632
  }),
367
- onClick: handleClick
633
+ onClick: (event) => {
634
+ var _a2;
635
+ if (!disabled && event.target !== inputRef.current) {
636
+ (_a2 = inputRef.current) == null ? void 0 : _a2.click();
637
+ }
638
+ }
368
639
  },
369
640
  /* @__PURE__ */ import_react.default.createElement(
370
641
  "input",
371
642
  __spreadProps(__spreadValues({
372
643
  type: "file",
644
+ "aria-label": "Upload file",
645
+ className: `${prefixCls}-native-input`,
373
646
  disabled
374
647
  }, acceptDirectory), {
375
- multiple,
648
+ multiple: Boolean(multiple || directory),
376
649
  accept,
377
650
  onChange: handleChange,
378
- style: { display: "none" },
379
651
  ref: inputRef
380
652
  })
381
653
  ),
382
- children ? children : listType === "picture-wall" ? /* @__PURE__ */ import_react.default.createElement("div", { className: `${prefixCls}-picture-wall-trigger` }, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Plus, null)) : /* @__PURE__ */ import_react.default.createElement(import_Button.default, { disabled }, "Upload")
654
+ children ? children : listType === "picture-wall" ? /* @__PURE__ */ import_react.default.createElement("span", { className: `${prefixCls}-picture-wall-trigger` }, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Plus, null)) : /* @__PURE__ */ import_react.default.createElement(import_Button.default, { disabled }, "Upload")
383
655
  );
384
656
  };
385
- const handleRemove = (file) => __async(void 0, null, function* () {
386
- const promise = onRemove == null ? void 0 : onRemove(file);
387
- const shouldRemove = promise instanceof Promise ? yield promise : promise !== false;
388
- if (shouldRemove !== false) {
389
- setMergedFileList(
390
- (state) => state.filter((item) => item.uid !== file.uid)
391
- );
392
- }
393
- });
394
- const handleReUpload = (file) => {
395
- const newFile = __spreadProps(__spreadValues({}, file), { status: "ready", percent: 0 });
396
- updateFileList(newFile);
397
- postFile(newFile);
398
- };
399
- const handlePreview = (file) => {
400
- if (onPreview) {
401
- onPreview(file);
402
- } else if (file.raw) {
403
- const url = URL.createObjectURL(file.raw);
404
- window.open(url);
405
- setTimeout(() => URL.revokeObjectURL(url), 100);
406
- }
407
- };
408
657
  const renderUploadList = (extraProps) => {
409
658
  if (!showUploadList) {
410
659
  return null;
@@ -420,7 +669,8 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
420
669
  itemRender,
421
670
  onRemove: handleRemove,
422
671
  onReUpload: handleReUpload,
423
- onPreview: handlePreview
672
+ onPreview: handlePreview,
673
+ isPreviewable: (file) => Boolean(onPreview || file.url || file.raw)
424
674
  }, extraProps)
425
675
  );
426
676
  };
@@ -428,7 +678,7 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
428
678
  return /* @__PURE__ */ import_react.default.createElement(
429
679
  "div",
430
680
  __spreadProps(__spreadValues({
431
- ref
681
+ ref: rootRef
432
682
  }, rest), {
433
683
  className: (0, import_clsx.default)(
434
684
  prefixCls,
@@ -444,7 +694,7 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
444
694
  /* @__PURE__ */ import_react.default.createElement(
445
695
  "div",
446
696
  {
447
- className: (0, import_clsx.default)(`${prefixCls}-drag-container`),
697
+ className: `${prefixCls}-drag-container`,
448
698
  onDrop: handleDrop,
449
699
  onDragOver: handleDragOver,
450
700
  onDragLeave: handleDragLeave
@@ -458,7 +708,7 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
458
708
  return /* @__PURE__ */ import_react.default.createElement(
459
709
  "div",
460
710
  __spreadProps(__spreadValues({
461
- ref
711
+ ref: rootRef
462
712
  }, rest), {
463
713
  className: (0, import_clsx.default)(prefixCls, `${prefixCls}-picture-wall`, className),
464
714
  style
@@ -469,7 +719,7 @@ var Upload = (0, import_react.forwardRef)((baseprops, ref) => {
469
719
  return /* @__PURE__ */ import_react.default.createElement(
470
720
  "div",
471
721
  __spreadProps(__spreadValues({
472
- ref
722
+ ref: rootRef
473
723
  }, rest), {
474
724
  className: (0, import_clsx.default)(
475
725
  prefixCls,