@vaadin/upload 25.0.3 → 25.1.0-alpha2

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.
@@ -205,6 +205,16 @@ export declare class UploadMixinClass {
205
205
  */
206
206
  uploadFormat: UploadFormat;
207
207
 
208
+ /**
209
+ * Specifies the maximum number of files that can be uploaded simultaneously.
210
+ * This helps prevent browser performance degradation and XHR limitations when
211
+ * uploading large numbers of files. Files exceeding this limit will be queued
212
+ * and uploaded as active uploads complete.
213
+ * @attr {number} max-concurrent-uploads
214
+ * @default 3
215
+ */
216
+ maxConcurrentUploads: number;
217
+
208
218
  /**
209
219
  * The object used to localize this component. To change the default
210
220
  * localization, replace this with an object that provides all properties, or
@@ -8,6 +8,7 @@ import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
8
8
  import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
9
9
  import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
10
10
  import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
11
+ import { getFilesFromDropEvent } from './vaadin-upload-helpers.js';
11
12
 
12
13
  export const DEFAULT_I18N = {
13
14
  dropFiles: {
@@ -322,6 +323,20 @@ export const UploadMixin = (superClass) =>
322
323
  value: 'raw',
323
324
  },
324
325
 
326
+ /**
327
+ * Specifies the maximum number of files that can be uploaded simultaneously.
328
+ * This helps prevent browser performance degradation and XHR limitations when
329
+ * uploading large numbers of files. Files exceeding this limit will be queued
330
+ * and uploaded as active uploads complete.
331
+ * @attr {number} max-concurrent-uploads
332
+ * @type {number}
333
+ */
334
+ maxConcurrentUploads: {
335
+ type: Number,
336
+ value: 3,
337
+ sync: true,
338
+ },
339
+
325
340
  /**
326
341
  * Pass-through to input's capture attribute. Allows user to trigger device inputs
327
342
  * such as camera or microphone immediately.
@@ -347,6 +362,18 @@ export const UploadMixin = (superClass) =>
347
362
  _files: {
348
363
  type: Array,
349
364
  },
365
+
366
+ /** @private */
367
+ _uploadQueue: {
368
+ type: Array,
369
+ value: () => [],
370
+ },
371
+
372
+ /** @private */
373
+ _activeUploads: {
374
+ type: Number,
375
+ value: 0,
376
+ },
350
377
  };
351
378
  }
352
379
 
@@ -590,59 +617,11 @@ export const UploadMixin = (superClass) =>
590
617
  event.preventDefault();
591
618
  this._dragover = this._dragoverValid = false;
592
619
 
593
- const files = await this.__getFilesFromDropEvent(event);
620
+ const files = await getFilesFromDropEvent(event);
594
621
  this._addFiles(files);
595
622
  }
596
623
  }
597
624
 
598
- /**
599
- * Get the files from the drop event. The dropped items may contain a
600
- * combination of files and directories. If a dropped item is a directory,
601
- * it will be recursively traversed to get all files.
602
- *
603
- * @param {!DragEvent} dropEvent - The drop event
604
- * @returns {Promise<File[]>} - The files from the drop event
605
- * @private
606
- */
607
- __getFilesFromDropEvent(dropEvent) {
608
- async function getFilesFromEntry(entry) {
609
- if (entry.isFile) {
610
- return new Promise((resolve) => {
611
- // In case of an error, resolve without any files
612
- entry.file(resolve, () => resolve([]));
613
- });
614
- } else if (entry.isDirectory) {
615
- const reader = entry.createReader();
616
- const entries = await new Promise((resolve) => {
617
- // In case of an error, resolve without any files
618
- reader.readEntries(resolve, () => resolve([]));
619
- });
620
- const files = await Promise.all(entries.map(getFilesFromEntry));
621
- return files.flat();
622
- }
623
- }
624
-
625
- // In some cases (like dragging attachments from Outlook on Windows), "webkitGetAsEntry"
626
- // can return null for "dataTransfer" items. Also, there is no reason to check for
627
- // "webkitGetAsEntry" when there are no folders. Therefore, "dataTransfer.files" is used
628
- // to handle such cases.
629
- const containsFolders = Array.from(dropEvent.dataTransfer.items)
630
- .filter((item) => !!item)
631
- .filter((item) => typeof item.webkitGetAsEntry === 'function')
632
- .map((item) => item.webkitGetAsEntry())
633
- .some((entry) => !!entry && entry.isDirectory);
634
- if (!containsFolders) {
635
- return Promise.resolve(dropEvent.dataTransfer.files ? Array.from(dropEvent.dataTransfer.files) : []);
636
- }
637
-
638
- const filePromises = Array.from(dropEvent.dataTransfer.items)
639
- .map((item) => item.webkitGetAsEntry())
640
- .filter((entry) => !!entry)
641
- .map(getFilesFromEntry);
642
-
643
- return Promise.all(filePromises).then((files) => files.flat());
644
- }
645
-
646
625
  /** @private */
647
626
  _createXhr() {
648
627
  return new XMLHttpRequest();
@@ -694,16 +673,46 @@ export const UploadMixin = (superClass) =>
694
673
  if (files && !Array.isArray(files)) {
695
674
  files = [files];
696
675
  }
697
- files = files.filter((file) => !file.complete);
698
- Array.prototype.forEach.call(files, this._uploadFile.bind(this));
676
+ files.filter((file) => !file.complete).forEach((file) => this._queueFileUpload(file));
699
677
  }
700
678
 
701
679
  /** @private */
702
- _uploadFile(file) {
680
+ _queueFileUpload(file) {
703
681
  if (file.uploading) {
704
682
  return;
705
683
  }
706
684
 
685
+ file.held = true;
686
+ file.uploading = file.indeterminate = true;
687
+ file.complete = file.abort = file.error = false;
688
+ file.status = this.__effectiveI18n.uploading.status.held;
689
+ this._renderFileList();
690
+
691
+ this._uploadQueue.push(file);
692
+ this._processUploadQueue();
693
+ }
694
+
695
+ /**
696
+ * Process the upload queue by starting uploads for queued files
697
+ * if there is available capacity.
698
+ *
699
+ * @private
700
+ */
701
+ _processUploadQueue() {
702
+ // Process as many queued files as we have capacity for
703
+ while (this._uploadQueue.length > 0 && this._activeUploads < this.maxConcurrentUploads) {
704
+ const nextFile = this._uploadQueue.shift();
705
+ if (nextFile) {
706
+ this._uploadFile(nextFile);
707
+ }
708
+ }
709
+ }
710
+
711
+ /** @private */
712
+ _uploadFile(file) {
713
+ // Increment active uploads counter
714
+ this._activeUploads += 1;
715
+
707
716
  const ini = Date.now();
708
717
  const xhr = (file.xhr = this._createXhr());
709
718
 
@@ -740,11 +749,22 @@ export const UploadMixin = (superClass) =>
740
749
  this.dispatchEvent(new CustomEvent('upload-progress', { detail: { file, xhr } }));
741
750
  };
742
751
 
752
+ xhr.onabort = () => {
753
+ // Decrement active uploads counter
754
+ this._activeUploads -= 1;
755
+ this._processUploadQueue();
756
+ };
757
+
743
758
  // More reliable than xhr.onload
744
759
  xhr.onreadystatechange = () => {
745
760
  if (xhr.readyState === 4) {
746
761
  clearTimeout(stalledId);
747
762
  file.indeterminate = file.uploading = false;
763
+
764
+ // Decrement active uploads counter
765
+ this._activeUploads -= 1;
766
+ this._processUploadQueue();
767
+
748
768
  if (file.abort) {
749
769
  return;
750
770
  }
@@ -815,9 +835,8 @@ export const UploadMixin = (superClass) =>
815
835
  xhr.open(this.method, file.uploadTarget, true);
816
836
  this._configureXhr(xhr, file, isRawUpload);
817
837
 
838
+ file.held = false;
818
839
  file.status = this.__effectiveI18n.uploading.status.connecting;
819
- file.uploading = file.indeterminate = true;
820
- file.complete = file.abort = file.error = file.held = false;
821
840
 
822
841
  xhr.upload.onloadstart = () => {
823
842
  this.dispatchEvent(
@@ -862,7 +881,7 @@ export const UploadMixin = (superClass) =>
862
881
  }),
863
882
  );
864
883
  if (evt) {
865
- this._uploadFile(file);
884
+ this._queueFileUpload(file);
866
885
  this._updateFocus(this.files.indexOf(file));
867
886
  }
868
887
  }
@@ -934,7 +953,7 @@ export const UploadMixin = (superClass) =>
934
953
  this.files = [file, ...this.files];
935
954
 
936
955
  if (!this.noAuto) {
937
- this._uploadFile(file);
956
+ this._queueFileUpload(file);
938
957
  }
939
958
  }
940
959
 
@@ -957,6 +976,9 @@ export const UploadMixin = (superClass) =>
957
976
  * @protected
958
977
  */
959
978
  _removeFile(file) {
979
+ this._uploadQueue = this._uploadQueue.filter((f) => f !== file);
980
+ this._processUploadQueue();
981
+
960
982
  const fileIndex = this.files.indexOf(file);
961
983
  if (fileIndex >= 0) {
962
984
  this.files = this.files.filter((i) => i !== file);
@@ -998,7 +1020,7 @@ export const UploadMixin = (superClass) =>
998
1020
 
999
1021
  /** @private */
1000
1022
  _onFileStart(event) {
1001
- this._uploadFile(event.detail.file);
1023
+ this._queueFileUpload(event.detail.file);
1002
1024
  }
1003
1025
 
1004
1026
  /** @private */
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-upload-button.js';
@@ -0,0 +1,3 @@
1
+ import './src/vaadin-upload-button.js';
2
+
3
+ export * from './src/vaadin-upload-button.js';
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-upload-drop-zone.js';
@@ -0,0 +1,3 @@
1
+ import './src/vaadin-upload-drop-zone.js';
2
+
3
+ export * from './src/vaadin-upload-drop-zone.js';
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-upload-file-list.js';
@@ -0,0 +1,3 @@
1
+ import './src/vaadin-upload-file-list.js';
2
+
3
+ export * from './src/vaadin-upload-file-list.js';
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-upload-manager.js';
@@ -0,0 +1 @@
1
+ export * from './src/vaadin-upload-manager.js';
package/web-types.json CHANGED
@@ -1,11 +1,167 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/upload",
4
- "version": "25.0.3",
4
+ "version": "25.1.0-alpha2",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
+ {
10
+ "name": "vaadin-upload-button",
11
+ "description": "`<vaadin-upload-button>` is a button component for file uploads.\nWhen clicked, it opens a file picker dialog and calls addFiles\non a linked UploadManager.\n\n```html\n<vaadin-upload-button>Upload Files</vaadin-upload-button>\n```\n\nThe button must be linked to an UploadManager by setting the\n`manager` property:\n\n```javascript\nconst button = document.querySelector('vaadin-upload-button');\nbutton.manager = uploadManager;\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------|-------------\n`label` | The label (text) inside the button.\n`prefix` | A slot for content before the label (e.g. an icon).\n`suffix` | A slot for content after the label (e.g. an icon).\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------|-------------\n`active` | Set when the button is pressed down, either with mouse, touch or the keyboard\n`disabled` | Set when the button is disabled\n`focus-ring` | Set when the button is focused using the keyboard\n`focused` | Set when the button is focused\n`has-tooltip` | Set when the button has a slotted tooltip\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:----------------------------------|\n| `--vaadin-button-background` |\n| `--vaadin-button-border-color` |\n| `--vaadin-button-border-radius` |\n| `--vaadin-button-border-width` |\n| `--vaadin-button-font-size` |\n| `--vaadin-button-font-weight` |\n| `--vaadin-button-gap` |\n| `--vaadin-button-height` |\n| `--vaadin-button-line-height` |\n| `--vaadin-button-margin` |\n| `--vaadin-button-padding` |\n| `--vaadin-button-text-color` |\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
12
+ "attributes": [
13
+ {
14
+ "name": "disabled",
15
+ "description": "If true, the user cannot interact with this element.",
16
+ "value": {
17
+ "type": [
18
+ "boolean",
19
+ "null",
20
+ "undefined"
21
+ ]
22
+ }
23
+ },
24
+ {
25
+ "name": "capture",
26
+ "description": "Capture attribute for mobile file input.",
27
+ "value": {
28
+ "type": [
29
+ "string"
30
+ ]
31
+ }
32
+ },
33
+ {
34
+ "name": "max-files-reached",
35
+ "description": "True when max files has been reached on the manager.",
36
+ "value": {
37
+ "type": [
38
+ "boolean"
39
+ ]
40
+ }
41
+ },
42
+ {
43
+ "name": "theme",
44
+ "description": "The theme variants to apply to the component.",
45
+ "value": {
46
+ "type": [
47
+ "string",
48
+ "null",
49
+ "undefined"
50
+ ]
51
+ }
52
+ }
53
+ ],
54
+ "js": {
55
+ "properties": [
56
+ {
57
+ "name": "disabled",
58
+ "description": "Whether the button is disabled.\nReturns true if either explicitly disabled or maxFilesReached is true.",
59
+ "value": {
60
+ "type": [
61
+ "?"
62
+ ]
63
+ }
64
+ },
65
+ {
66
+ "name": "manager",
67
+ "description": "Reference to an UploadManager.\nWhen set, the button will automatically disable when maxFilesReached\nbecomes true on the manager.",
68
+ "value": {
69
+ "type": [
70
+ "Object",
71
+ "null"
72
+ ]
73
+ }
74
+ },
75
+ {
76
+ "name": "capture",
77
+ "description": "Capture attribute for mobile file input.",
78
+ "value": {
79
+ "type": [
80
+ "string"
81
+ ]
82
+ }
83
+ },
84
+ {
85
+ "name": "maxFilesReached",
86
+ "description": "True when max files has been reached on the manager.",
87
+ "value": {
88
+ "type": [
89
+ "boolean"
90
+ ]
91
+ }
92
+ }
93
+ ],
94
+ "events": []
95
+ }
96
+ },
97
+ {
98
+ "name": "vaadin-upload-drop-zone",
99
+ "description": "`<vaadin-upload-drop-zone>` is a Web Component that can be used as a drop zone\nfor file uploads. When files are dropped on the drop zone, they are added to\na linked UploadManager.\n\n```html\n<vaadin-upload-drop-zone>\n <p>Drop files here</p>\n</vaadin-upload-drop-zone>\n```\n\nThe drop zone must be linked to an UploadManager by setting the\n`manager` property:\n\n```javascript\nconst dropZone = document.querySelector('vaadin-upload-drop-zone');\ndropZone.manager = uploadManager;\n```\n\n### Styling\n\nThe component has no styling by default. When files are dragged over,\nthe `dragover` attribute is set and the component uses a hover effect.\nTo override the hover effect, use `vaadin-upload-drop-zone[dragover]::after`\nselector to style the pseudo-element covering the drop zone during dragover.\n\nAttribute | Description\n-------------------|--------------------------------------------\n`dragover` | Set when files are being dragged over the element\n`disabled` | Set when the drop zone is explicitly disabled\n`max-files-reached`| Set when the manager has reached maxFiles\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
100
+ "attributes": [
101
+ {
102
+ "name": "disabled",
103
+ "description": "Whether the drop zone is disabled.",
104
+ "value": {
105
+ "type": [
106
+ "boolean"
107
+ ]
108
+ }
109
+ },
110
+ {
111
+ "name": "max-files-reached",
112
+ "description": "True when max files has been reached on the manager.",
113
+ "value": {
114
+ "type": [
115
+ "boolean"
116
+ ]
117
+ }
118
+ },
119
+ {
120
+ "name": "theme",
121
+ "description": "The theme variants to apply to the component.",
122
+ "value": {
123
+ "type": [
124
+ "string",
125
+ "null",
126
+ "undefined"
127
+ ]
128
+ }
129
+ }
130
+ ],
131
+ "js": {
132
+ "properties": [
133
+ {
134
+ "name": "manager",
135
+ "description": "Reference to an UploadManager.\nWhen set, dropped files will be automatically added to the manager.",
136
+ "value": {
137
+ "type": [
138
+ "Object",
139
+ "null"
140
+ ]
141
+ }
142
+ },
143
+ {
144
+ "name": "disabled",
145
+ "description": "Whether the drop zone is disabled.",
146
+ "value": {
147
+ "type": [
148
+ "boolean"
149
+ ]
150
+ }
151
+ },
152
+ {
153
+ "name": "maxFilesReached",
154
+ "description": "True when max files has been reached on the manager.",
155
+ "value": {
156
+ "type": [
157
+ "boolean"
158
+ ]
159
+ }
160
+ }
161
+ ],
162
+ "events": []
163
+ }
164
+ },
9
165
  {
10
166
  "name": "vaadin-upload-file",
11
167
  "description": "`<vaadin-upload-file>` element represents a file in the file list of `<vaadin-upload>`.\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------\n`done-icon` | File done status icon\n`warning-icon` | File warning status icon\n`meta` | Container for file name, status and error messages\n`name` | File name\n`error` | Error message, shown when error happens\n`status` | Status message\n`commands` | Container for file command buttons\n`start-button` | Start file upload button\n`retry-button` | Retry file upload button\n`remove-button` | Remove file button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|-------------\n`disabled` | Set when the element is disabled\n`focus-ring` | Set when the element is focused using the keyboard.\n`focused` | Set when the element is focused.\n`error` | An error has happened during uploading.\n`indeterminate` | Uploading is in progress, but the progress value is unknown.\n`uploading` | Uploading is in progress.\n`complete` | Uploading has finished successfully.\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------|\n`--vaadin-upload-file-border-radius` |\n`--vaadin-upload-file-button-background` |\n`--vaadin-upload-file-button-border-color` |\n`--vaadin-upload-file-button-border-radius` |\n`--vaadin-upload-file-button-border-width` |\n`--vaadin-upload-file-button-text-color` |\n`--vaadin-upload-file-button-padding` |\n`--vaadin-upload-file-done-color` |\n`--vaadin-upload-file-error-color` |\n`--vaadin-upload-file-error-font-size` |\n`--vaadin-upload-file-error-font-weight` |\n`--vaadin-upload-file-error-line-height` |\n`--vaadin-upload-file-gap` |\n`--vaadin-upload-file-name-color` |\n`--vaadin-upload-file-name-font-size` |\n`--vaadin-upload-file-name-font-weight` |\n`--vaadin-upload-file-name-line-height` |\n`--vaadin-upload-file-padding` |\n`--vaadin-upload-file-status-color` |\n`--vaadin-upload-file-status-font-size` |\n`--vaadin-upload-file-status-font-weight` |\n`--vaadin-upload-file-status-line-height` |\n`--vaadin-upload-file-warning-color` |\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
@@ -261,6 +417,89 @@
261
417
  ]
262
418
  }
263
419
  },
420
+ {
421
+ "name": "vaadin-upload-file-list",
422
+ "description": "`<vaadin-upload-file-list>` is a Web Component that displays a list of uploaded files.\nIt automatically syncs files from the manager and forwards file events back to it.\n\n```html\n<vaadin-upload-file-list></vaadin-upload-file-list>\n```\n\nThe file list must be linked to an UploadManager by setting the `manager` property:\n\n```javascript\nimport { UploadManager } from '@vaadin/upload/vaadin-upload-manager.js';\n\nconst manager = new UploadManager({ target: '/api/upload' });\nconst fileList = document.querySelector('vaadin-upload-file-list');\nfileList.manager = manager;\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n----------|-------------\n`list` | The `<ul>` element wrapping the file items\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------|-------------\n`disabled` | Set when the element is disabled\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------|\n`--vaadin-upload-file-list-divider-color` |\n`--vaadin-upload-file-list-divider-width` |\n`--vaadin-upload-file-border-radius` |\n`--vaadin-upload-file-button-background` |\n`--vaadin-upload-file-button-border-color` |\n`--vaadin-upload-file-button-border-radius` |\n`--vaadin-upload-file-button-border-width` |\n`--vaadin-upload-file-button-text-color` |\n`--vaadin-upload-file-button-padding` |\n`--vaadin-upload-file-done-color` |\n`--vaadin-upload-file-error-color` |\n`--vaadin-upload-file-error-font-size` |\n`--vaadin-upload-file-error-font-weight` |\n`--vaadin-upload-file-error-line-height` |\n`--vaadin-upload-file-gap` |\n`--vaadin-upload-file-name-color` |\n`--vaadin-upload-file-name-font-size` |\n`--vaadin-upload-file-name-font-weight` |\n`--vaadin-upload-file-name-line-height` |\n`--vaadin-upload-file-padding` |\n`--vaadin-upload-file-status-color` |\n`--vaadin-upload-file-status-font-size` |\n`--vaadin-upload-file-status-font-weight` |\n`--vaadin-upload-file-status-line-height` |\n`--vaadin-upload-file-warning-color` |\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
423
+ "attributes": [
424
+ {
425
+ "name": "i18n",
426
+ "description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nShould be overridden by subclasses to provide a custom JSDoc with the\ndefault I18N properties.",
427
+ "value": {
428
+ "type": [
429
+ "Object"
430
+ ]
431
+ }
432
+ },
433
+ {
434
+ "name": "disabled",
435
+ "description": "If true, the user cannot interact with this element.",
436
+ "value": {
437
+ "type": [
438
+ "boolean",
439
+ "null",
440
+ "undefined"
441
+ ]
442
+ }
443
+ },
444
+ {
445
+ "name": "theme",
446
+ "description": "The theme variants to apply to the component.",
447
+ "value": {
448
+ "type": [
449
+ "string",
450
+ "null",
451
+ "undefined"
452
+ ]
453
+ }
454
+ }
455
+ ],
456
+ "js": {
457
+ "properties": [
458
+ {
459
+ "name": "i18n",
460
+ "description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nShould be overridden by subclasses to provide a custom JSDoc with the\ndefault I18N properties.",
461
+ "value": {
462
+ "type": [
463
+ "Object"
464
+ ]
465
+ }
466
+ },
467
+ {
468
+ "name": "items",
469
+ "description": "The array of files being processed, or already uploaded.",
470
+ "value": {
471
+ "type": [
472
+ "Array",
473
+ "null",
474
+ "undefined"
475
+ ]
476
+ }
477
+ },
478
+ {
479
+ "name": "disabled",
480
+ "description": "If true, the user cannot interact with this element.",
481
+ "value": {
482
+ "type": [
483
+ "boolean",
484
+ "null",
485
+ "undefined"
486
+ ]
487
+ }
488
+ },
489
+ {
490
+ "name": "manager",
491
+ "description": "Reference to an UploadManager to link this file list to.\nWhen set, the file list automatically:\n- Syncs files from the manager\n- Forwards retry/abort/start/remove events back to the manager",
492
+ "value": {
493
+ "type": [
494
+ "Object",
495
+ "null"
496
+ ]
497
+ }
498
+ }
499
+ ],
500
+ "events": []
501
+ }
502
+ },
264
503
  {
265
504
  "name": "vaadin-upload",
266
505
  "description": "`<vaadin-upload>` is a Web Component for uploading multiple files with drag and drop support.\n\nExample:\n\n```html\n<vaadin-upload></vaadin-upload>\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-------------------|-------------------------------------\n`primary-buttons` | Upload container\n`drop-label` | Element wrapping drop label and icon\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|---------------------------------\n`disabled` | Set when the element is disabled\n`nodrop` | Set when drag and drop is disabled (e.g., on touch devices)\n`dragover` | Set when the file is being dragged over the element\n`dragover-valid` | Set when the dragged file is valid with `maxFiles` and `accept` criteria\n`max-files-reached` | Set when maximum number of files that the user is allowed to add has been reached\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------|\n`--vaadin-upload-background` |\n`--vaadin-upload-border-color` |\n`--vaadin-upload-border-radius` |\n`--vaadin-upload-border-width` |\n`--vaadin-upload-gap` |\n`--vaadin-upload-padding` |\n`--vaadin-upload-drop-label-color` |\n`--vaadin-upload-drop-label-font-size` |\n`--vaadin-upload-drop-label-font-weight` |\n`--vaadin-upload-drop-label-gap` |\n`--vaadin-upload-drop-label-line-height` |\n`--vaadin-upload-file-list-divider-color` |\n`--vaadin-upload-file-list-divider-width` |\n`--vaadin-upload-file-border-radius` |\n`--vaadin-upload-file-button-background` |\n`--vaadin-upload-file-button-border-color` |\n`--vaadin-upload-file-button-border-radius` |\n`--vaadin-upload-file-button-border-width` |\n`--vaadin-upload-file-button-text-color` |\n`--vaadin-upload-file-button-padding` |\n`--vaadin-upload-file-done-color` |\n`--vaadin-upload-file-error-color` |\n`--vaadin-upload-file-error-font-size` |\n`--vaadin-upload-file-error-font-weight` |\n`--vaadin-upload-file-error-line-height` |\n`--vaadin-upload-file-gap` |\n`--vaadin-upload-file-name-color` |\n`--vaadin-upload-file-name-font-size` |\n`--vaadin-upload-file-name-font-weight` |\n`--vaadin-upload-file-name-line-height` |\n`--vaadin-upload-file-padding` |\n`--vaadin-upload-file-status-color` |\n`--vaadin-upload-file-status-font-size` |\n`--vaadin-upload-file-status-font-weight` |\n`--vaadin-upload-file-status-line-height` |\n`--vaadin-upload-file-warning-color` |\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
@@ -373,6 +612,15 @@
373
612
  ]
374
613
  }
375
614
  },
615
+ {
616
+ "name": "max-concurrent-uploads",
617
+ "description": "Specifies the maximum number of files that can be uploaded simultaneously.\nThis helps prevent browser performance degradation and XHR limitations when\nuploading large numbers of files. Files exceeding this limit will be queued\nand uploaded as active uploads complete.",
618
+ "value": {
619
+ "type": [
620
+ "number"
621
+ ]
622
+ }
623
+ },
376
624
  {
377
625
  "name": "capture",
378
626
  "description": "Pass-through to input's capture attribute. Allows user to trigger device inputs\nsuch as camera or microphone immediately.",
@@ -534,6 +782,15 @@
534
782
  ]
535
783
  }
536
784
  },
785
+ {
786
+ "name": "maxConcurrentUploads",
787
+ "description": "Specifies the maximum number of files that can be uploaded simultaneously.\nThis helps prevent browser performance degradation and XHR limitations when\nuploading large numbers of files. Files exceeding this limit will be queued\nand uploaded as active uploads complete.",
788
+ "value": {
789
+ "type": [
790
+ "number"
791
+ ]
792
+ }
793
+ },
537
794
  {
538
795
  "name": "capture",
539
796
  "description": "Pass-through to input's capture attribute. Allows user to trigger device inputs\nsuch as camera or microphone immediately.",