@vaadin/upload 25.2.7 → 25.3.0-alpha10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/upload",
3
- "version": "25.2.7",
3
+ "version": "25.3.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -35,19 +35,19 @@
35
35
  ],
36
36
  "dependencies": {
37
37
  "@open-wc/dedupe-mixin": "^1.3.0",
38
- "@vaadin/a11y-base": "~25.2.7",
39
- "@vaadin/button": "~25.2.7",
40
- "@vaadin/component-base": "~25.2.7",
41
- "@vaadin/progress-bar": "~25.2.7",
42
- "@vaadin/vaadin-themable-mixin": "~25.2.7",
38
+ "@vaadin/a11y-base": "25.3.0-alpha10",
39
+ "@vaadin/button": "25.3.0-alpha10",
40
+ "@vaadin/component-base": "25.3.0-alpha10",
41
+ "@vaadin/progress-bar": "25.3.0-alpha10",
42
+ "@vaadin/vaadin-themable-mixin": "25.3.0-alpha10",
43
43
  "lit": "^3.0.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@vaadin/aura": "~25.2.7",
47
- "@vaadin/chai-plugins": "~25.2.7",
48
- "@vaadin/test-runner-commands": "~25.2.7",
46
+ "@vaadin/aura": "25.3.0-alpha10",
47
+ "@vaadin/chai-plugins": "25.3.0-alpha10",
48
+ "@vaadin/test-runner-commands": "25.3.0-alpha10",
49
49
  "@vaadin/testing-helpers": "^2.0.0",
50
- "@vaadin/vaadin-lumo-styles": "~25.2.7",
50
+ "@vaadin/vaadin-lumo-styles": "25.3.0-alpha10",
51
51
  "sinon": "^22.0.0"
52
52
  },
53
53
  "customElements": "custom-elements.json",
@@ -55,5 +55,5 @@
55
55
  "web-types.json",
56
56
  "web-types.lit.json"
57
57
  ],
58
- "gitHead": "14be1af674f3968cce68c6eb4742340694c4a949"
58
+ "gitHead": "f2833abdf9b613fa0d0ed216830e3f4de87b7dac"
59
59
  }
@@ -6,6 +6,7 @@
6
6
  import { html, LitElement } from 'lit';
7
7
  import { ButtonMixin } from '@vaadin/button/src/vaadin-button-mixin.js';
8
8
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
9
+ import { setOrRemoveAttribute } from '@vaadin/component-base/src/dom-utils.js';
9
10
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
10
11
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
11
12
  import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
@@ -70,6 +71,7 @@ import { UploadManager } from './vaadin-upload-manager.js';
70
71
  *
71
72
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
72
73
  *
74
+ * @attr {string} theme - The theme variants to apply to the component.
73
75
  * @customElement vaadin-upload-button
74
76
  * @extends HTMLElement
75
77
  */
@@ -213,22 +215,14 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
213
215
 
214
216
  // Set accept attribute from manager
215
217
  const accept = this.manager && this.manager.accept;
216
- if (accept) {
217
- fileInput.setAttribute('accept', accept);
218
- } else {
219
- fileInput.removeAttribute('accept');
220
- }
218
+ setOrRemoveAttribute(fileInput, 'accept', accept);
221
219
 
222
220
  // Set multiple attribute based on manager's maxFiles
223
221
  const maxFiles = this.manager && this.manager.maxFiles != null ? this.manager.maxFiles : Infinity;
224
222
  fileInput.multiple = maxFiles !== 1;
225
223
 
226
224
  // Set capture attribute
227
- if (this.capture) {
228
- fileInput.setAttribute('capture', this.capture);
229
- } else {
230
- fileInput.removeAttribute('capture');
231
- }
225
+ setOrRemoveAttribute(fileInput, 'capture', this.capture);
232
226
  }
233
227
 
234
228
  /** @private */
@@ -47,6 +47,7 @@ import { UploadManager } from './vaadin-upload-manager.js';
47
47
  *
48
48
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
49
49
  *
50
+ * @attr {string} theme - The theme variants to apply to the component.
50
51
  * @customElement vaadin-upload-drop-zone
51
52
  * @extends HTMLElement
52
53
  */
@@ -33,6 +33,7 @@ export interface UploadFileListI18n {
33
33
  serverUnavailable?: string;
34
34
  unexpectedServerError?: string;
35
35
  forbidden?: string;
36
+ fileTooLarge?: string;
36
37
  };
37
38
  };
38
39
  units?: {
@@ -6,9 +6,10 @@
6
6
  import { html, render } from 'lit';
7
7
  import { ifDefined } from 'lit/directives/if-defined.js';
8
8
  import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
9
+ import { translateErrorKey, updateFileStatus } from './vaadin-upload-helpers.js';
9
10
  import { UploadManager } from './vaadin-upload-manager.js';
10
11
 
11
- const DEFAULT_I18N = {
12
+ export const DEFAULT_I18N = {
12
13
  file: {
13
14
  retry: 'Retry',
14
15
  start: 'Start',
@@ -267,124 +268,30 @@ export const UploadFileListMixin = (superClass) =>
267
268
  __applyI18nToFile(file) {
268
269
  const i18n = this.__effectiveI18n;
269
270
 
270
- // Always set size-related strings when total is available
271
- if (file.total) {
272
- this.__applyFileSizeStrings(file);
273
- }
274
-
275
- // Apply status messages based on file state
276
- file.status = this.__getFileStatus(file, i18n);
271
+ // Apply size and status strings based on file state
272
+ updateFileStatus(file, i18n, { indeterminateFirst: true });
277
273
 
278
274
  // Translate error codes to i18n messages
279
275
  this.__applyFileError(file, i18n);
280
276
  }
281
277
 
282
- /** @private */
283
- __applyFileSizeStrings(file) {
284
- file.totalStr = this.__formatSize(file.total);
285
- file.loadedStr = this.__formatSize(file.loaded || 0);
286
- // TODO: Remove elapsedStr in next major version - it's not used by vaadin-upload-file
287
- if (file.elapsed != null) {
288
- file.elapsedStr = this.__formatTime(file.elapsed, this.__splitTimeByUnits(file.elapsed));
289
- }
290
- if (file.remaining != null) {
291
- file.remainingStr = this.__formatTime(file.remaining, this.__splitTimeByUnits(file.remaining));
292
- }
293
- }
294
-
295
- /** @private */
296
- __getFileStatus(file, i18n) {
297
- if (file.held && !file.error) {
298
- // File is queued and waiting
299
- return i18n.uploading.status.held;
300
- }
301
- if (file.stalled) {
302
- // File upload is stalled
303
- return i18n.uploading.status.stalled;
304
- }
305
- if (file.uploading && file.indeterminate && !file.held) {
306
- // File is uploading but progress is indeterminate (connecting or processing)
307
- return file.progress === 100 ? i18n.uploading.status.processing : i18n.uploading.status.connecting;
308
- }
309
- if (file.uploading && file.progress < 100 && file.total) {
310
- // File is uploading with known progress
311
- return this.__formatFileProgress(file);
312
- }
313
- return file.status;
314
- }
315
-
316
278
  /** @private */
317
279
  __applyFileError(file, i18n) {
318
- if (file.errorKey && i18n.uploading.error[file.errorKey]) {
319
- file.error = i18n.uploading.error[file.errorKey];
280
+ // An error key without an i18n message (e.g. a failure to send the
281
+ // request) leaves the error assigned to the file untouched
282
+ const error = file.errorKey && translateErrorKey(file.errorKey, i18n);
283
+ if (error) {
284
+ file.error = error;
320
285
  } else if (!file.errorKey && this.manager instanceof UploadManager) {
321
286
  // Clear error when errorKey is reset (e.g., on retry) only when using manager
322
287
  file.error = '';
323
288
  }
324
289
  }
325
290
 
326
- /** @private */
327
- __formatSize(bytes) {
328
- const i18n = this.__effectiveI18n;
329
- if (typeof i18n.formatSize === 'function') {
330
- return i18n.formatSize(bytes);
331
- }
332
-
333
- // https://wiki.ubuntu.com/UnitsPolicy
334
- const base = i18n.units.sizeBase || 1000;
335
- const unit = Math.trunc(Math.log(bytes) / Math.log(base));
336
- const dec = Math.max(0, Math.min(3, unit - 1));
337
- const size = Number.parseFloat((bytes / base ** unit).toFixed(dec));
338
- return `${size} ${i18n.units.size[unit]}`;
339
- }
340
-
341
- /** @private */
342
- __splitTimeByUnits(time) {
343
- const unitSizes = [60, 60, 24, Infinity];
344
- const timeValues = [0];
345
-
346
- for (let i = 0; i < unitSizes.length && time > 0; i++) {
347
- timeValues[i] = time % unitSizes[i];
348
- time = Math.floor(time / unitSizes[i]);
349
- }
350
-
351
- return timeValues;
352
- }
353
-
354
- /** @private */
355
- __formatTime(seconds, split) {
356
- const i18n = this.__effectiveI18n;
357
- if (typeof i18n.formatTime === 'function') {
358
- return i18n.formatTime(seconds, split);
359
- }
360
-
361
- // Fill HH:MM:SS with leading zeros
362
- while (split.length < 3) {
363
- split.push(0);
364
- }
365
-
366
- return split
367
- .reverse()
368
- .map((number) => {
369
- return (number < 10 ? '0' : '') + number;
370
- })
371
- .join(':');
372
- }
373
-
374
- /** @private */
375
- __formatFileProgress(file) {
376
- const i18n = this.__effectiveI18n;
377
- const remainingTime =
378
- file.loaded > 0
379
- ? i18n.uploading.remainingTime.prefix + file.remainingStr
380
- : i18n.uploading.remainingTime.unknown;
381
-
382
- return `${file.totalStr}: ${file.progress}% (${remainingTime})`;
383
- }
384
-
385
291
  /** @private */
386
292
  requestContentUpdate() {
387
293
  const { items, __effectiveI18n: i18n, disabled } = this;
294
+
388
295
  const managerDisabled = this.manager instanceof UploadManager && this.manager.disabled;
389
296
  const effectiveDisabled = disabled || managerDisabled;
390
297
 
@@ -75,6 +75,7 @@ import { UploadFileListMixin } from './vaadin-upload-file-list-mixin.js';
75
75
  *
76
76
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
77
77
  *
78
+ * @attr {string} theme - The theme variants to apply to the component.
78
79
  * @customElement vaadin-upload-file-list
79
80
  * @extends HTMLElement
80
81
  */
@@ -167,15 +167,6 @@ export const UploadFileMixin = (superClass) =>
167
167
  return event.composedPath()[0] === this;
168
168
  }
169
169
 
170
- /** @private */
171
- __disabledChanged(disabled) {
172
- if (disabled) {
173
- this.removeAttribute('tabindex');
174
- } else {
175
- this.setAttribute('tabindex', this.tabindex);
176
- }
177
- }
178
-
179
170
  /** @private */
180
171
  _errorMessageChanged(errorMessage) {
181
172
  this.toggleAttribute('error', Boolean(errorMessage));
@@ -81,6 +81,7 @@ import { UploadFileMixin } from './vaadin-upload-file-mixin.js';
81
81
  * @fires {CustomEvent} file-retry - Fired when the retry button is pressed to request retrying the upload of this file.
82
82
  * @fires {CustomEvent} file-start - Fired when the start button is pressed to request starting the upload of this file.
83
83
  *
84
+ * @attr {string} theme - The theme variants to apply to the component.
84
85
  * @customElement vaadin-upload-file
85
86
  * @extends HTMLElement
86
87
  */
@@ -105,11 +106,13 @@ class UploadFile extends UploadFileMixin(ThemableMixin(PolylitMixin(LumoInjectio
105
106
  return html`
106
107
  <div part="loader" ?hidden="${!this.uploading}" aria-hidden="true"></div>
107
108
 
108
- ${this.__thumbnail
109
- ? html`<div part="thumbnail">
110
- <img src="${this.__thumbnail}" alt="${this.fileName}" />
111
- </div>`
112
- : nothing}
109
+ ${
110
+ this.__thumbnail
111
+ ? html`<div part="thumbnail">
112
+ <img src="${this.__thumbnail}" alt="${this.fileName}" />
113
+ </div>`
114
+ : nothing
115
+ }
113
116
 
114
117
  <div part="done-icon" ?hidden="${!this.complete}" aria-hidden="true"></div>
115
118
  <div part="warning-icon" ?hidden="${!this.errorMessage}" aria-hidden="true"></div>
@@ -4,6 +4,149 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
7
+ /**
8
+ * Format the given number of bytes with the units defined by the i18n object,
9
+ * or with the custom `formatSize` function if the i18n object provides one.
10
+ *
11
+ * @param {number} bytes - The size in bytes
12
+ * @param {Object} i18n - The effective i18n object
13
+ * @returns {string} - The formatted size
14
+ * @private
15
+ */
16
+ function formatSize(bytes, i18n) {
17
+ if (typeof i18n.formatSize === 'function') {
18
+ return i18n.formatSize(bytes);
19
+ }
20
+
21
+ // https://wiki.ubuntu.com/UnitsPolicy
22
+ const base = i18n.units.sizeBase || 1000;
23
+ const unit = bytes > 0 ? Math.trunc(Math.log(bytes) / Math.log(base)) : 0;
24
+ const dec = Math.max(0, Math.min(3, unit - 1));
25
+ const size = Number.parseFloat((bytes / base ** unit).toFixed(dec));
26
+ return `${size} ${i18n.units.size[unit]}`;
27
+ }
28
+
29
+ /** @private */
30
+ function splitTimeByUnits(time) {
31
+ const unitSizes = [60, 60, 24, Infinity];
32
+ const timeValues = [0];
33
+
34
+ for (let i = 0; i < unitSizes.length && time > 0; i++) {
35
+ timeValues[i] = time % unitSizes[i];
36
+ time = Math.floor(time / unitSizes[i]);
37
+ }
38
+
39
+ return timeValues;
40
+ }
41
+
42
+ /**
43
+ * Format the given time in seconds as a 'HH:MM:SS' string, or with the
44
+ * custom `formatTime` function if the i18n object provides one.
45
+ *
46
+ * @param {number} seconds - The time in seconds
47
+ * @param {Object} i18n - The effective i18n object
48
+ * @returns {string} - The formatted time
49
+ * @private
50
+ */
51
+ function formatTime(seconds, i18n) {
52
+ const split = splitTimeByUnits(seconds);
53
+ if (typeof i18n.formatTime === 'function') {
54
+ return i18n.formatTime(seconds, split);
55
+ }
56
+
57
+ // Fill HH:MM:SS with leading zeros
58
+ while (split.length < 3) {
59
+ split.push(0);
60
+ }
61
+
62
+ return split
63
+ .reverse()
64
+ .map((number) => {
65
+ return (number < 10 ? '0' : '') + number;
66
+ })
67
+ .join(':');
68
+ }
69
+
70
+ /** @private */
71
+ function formatFileProgress(file, i18n) {
72
+ const remainingTime =
73
+ file.loaded > 0 ? i18n.uploading.remainingTime.prefix + file.remainingStr : i18n.uploading.remainingTime.unknown;
74
+
75
+ return `${file.totalStr}: ${file.progress}% (${remainingTime})`;
76
+ }
77
+
78
+ /** @private */
79
+ function getFileStatus(file, i18n, indeterminateFirst) {
80
+ if (file.held && !file.error) {
81
+ // File is queued and waiting
82
+ return i18n.uploading.status.held;
83
+ }
84
+ if (file.stalled) {
85
+ // File upload is stalled
86
+ return i18n.uploading.status.stalled;
87
+ }
88
+ // A progress event has arrived, show the progress even when no bytes
89
+ // have been transferred yet (formatted as unknown remaining time)
90
+ const progressStatus =
91
+ file.uploading && file.progress < 100 && file.total ? formatFileProgress(file, i18n) : undefined;
92
+ if (progressStatus && !indeterminateFirst) {
93
+ return progressStatus;
94
+ }
95
+ if (file.uploading && file.indeterminate && !file.held) {
96
+ // File is uploading but progress is indeterminate (connecting or processing)
97
+ return file.progress === 100 ? i18n.uploading.status.processing : i18n.uploading.status.connecting;
98
+ }
99
+ if (progressStatus) {
100
+ return progressStatus;
101
+ }
102
+ return file.status;
103
+ }
104
+
105
+ /**
106
+ * Update the human-readable status and size strings of the given file
107
+ * based on its upload state, using the given i18n object for formatting.
108
+ *
109
+ * @param {Object} file - The file to update
110
+ * @param {Object} i18n - The effective i18n object
111
+ * @param {Object} [options]
112
+ * @param {boolean} [options.indeterminateFirst=false] - Give the
113
+ * indeterminate statuses (connecting, processing) precedence over the
114
+ * transfer progress, like `<vaadin-upload-file-list>` historically does.
115
+ * @private
116
+ */
117
+ export function updateFileStatus(file, i18n, { indeterminateFirst = false } = {}) {
118
+ // Always set size-related strings when total is available
119
+ if (file.total) {
120
+ file.totalStr = formatSize(file.total, i18n);
121
+ file.loadedStr = formatSize(file.loaded || 0, i18n);
122
+ // TODO: Remove elapsedStr in next major version - it's not used by vaadin-upload-file
123
+ if (file.elapsed != null) {
124
+ file.elapsedStr = formatTime(file.elapsed, i18n);
125
+ }
126
+ if (file.remaining != null) {
127
+ file.remainingStr = formatTime(file.remaining, i18n);
128
+ }
129
+ }
130
+
131
+ // Apply status message based on file state
132
+ file.status = getFileStatus(file, i18n, indeterminateFirst);
133
+ }
134
+
135
+ /**
136
+ * Translate the error key of a failed upload into the matching i18n error
137
+ * message. A timed out request is reported as server unavailable.
138
+ *
139
+ * @param {string} errorKey - The error key of a failed upload
140
+ * @param {Object} i18n - The effective i18n object
141
+ * @returns {string | undefined} - The translated error message, or `undefined`
142
+ * when the i18n object has no message for the key
143
+ * @private
144
+ */
145
+ export function translateErrorKey(errorKey, i18n) {
146
+ const key = errorKey === 'timeout' ? 'serverUnavailable' : errorKey;
147
+ return i18n.uploading.error[key];
148
+ }
149
+
7
150
  /**
8
151
  * Get the files from the drop event. The dropped items may contain a
9
152
  * combination of files and directories. If a dropped item is a directory,
@@ -12,6 +12,7 @@ import { uploadIconStyles } from './styles/vaadin-upload-icon-base-styles.js';
12
12
  /**
13
13
  * An element used internally by `<vaadin-upload>`. Not intended to be used separately.
14
14
  *
15
+ * @attr {string} theme - The theme variants to apply to the component.
15
16
  * @customElement vaadin-upload-icon
16
17
  * @extends HTMLElement
17
18
  * @private
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { UploadManager } from './vaadin-upload-manager.js';
7
+
8
+ /**
9
+ * The `headers` property also supports a JSON string, while the manager only
10
+ * accepts an object, so strings are parsed. An invalid JSON string parses to
11
+ * undefined, which throws when the request is configured.
12
+ */
13
+ export function parseHeaders(headers) {
14
+ if (typeof headers !== 'string') {
15
+ return headers;
16
+ }
17
+ try {
18
+ return JSON.parse(headers);
19
+ } catch (_) {
20
+ return undefined;
21
+ }
22
+ }
23
+
24
+ // The manager configuration derived from the component properties. Each entry
25
+ // is defined as a getter on `InternalUploadManager`, so that the manager reads
26
+ // the current value whenever it needs it. This way configuration changed by an
27
+ // `upload-before` listener (e.g. headers with a fresh auth token) applies to
28
+ // the request being started, like it historically did.
29
+ //
30
+ // `formDataName` is not included: the `upload-before` listener assigns it to
31
+ // the file when the upload starts, like the component has historically done.
32
+ const MANAGER_CONFIG = {
33
+ // Fall back to an empty string, which means that window.location will be
34
+ // used, also when the property is set to null
35
+ target: (host) => host.target || '',
36
+ // Unlike the manager, the component passes an unsupported method to the
37
+ // request as-is instead of throwing
38
+ method: (host) => host.method,
39
+ headers: (host) => parseHeaders(host.headers),
40
+ timeout: (host) => host.timeout,
41
+ noAuto: (host) => host.noAuto,
42
+ withCredentials: (host) => host.withCredentials,
43
+ uploadFormat: (host) => host.uploadFormat,
44
+ // Unlike the manager, the component pauses uploads on a non-positive value
45
+ // instead of throwing
46
+ maxConcurrentUploads: (host) => host.maxConcurrentUploads,
47
+ // Unlike the manager, the component treats a negative value as no limit
48
+ maxFiles: (host) => (host.maxFiles < 0 ? Infinity : host.maxFiles),
49
+ maxFileSize: (host) => host.maxFileSize,
50
+ accept: (host) => host.accept,
51
+ };
52
+
53
+ /**
54
+ * An `UploadManager` subclass used internally by `<vaadin-upload>`. It reads
55
+ * its configuration from the host component, and overrides the manager
56
+ * behavior where the component behavior that predates the manager integration
57
+ * differs from the standalone manager.
58
+ */
59
+ export class InternalUploadManager extends UploadManager {
60
+ /**
61
+ * @param {HTMLElement} host The `<vaadin-upload>` element to read the
62
+ * configuration from
63
+ */
64
+ constructor(host) {
65
+ super();
66
+ this.__host = host;
67
+ }
68
+
69
+ /**
70
+ * Override accessor from `UploadManager` to accept assigned files as-is,
71
+ * without validating them against the maxFiles, maxFileSize and accept
72
+ * constraints, e.g. to show previously uploaded files.
73
+ * @override
74
+ */
75
+ get files() {
76
+ return super.files;
77
+ }
78
+
79
+ set files(files) {
80
+ this._setFiles([...files]);
81
+ }
82
+
83
+ /**
84
+ * Start the upload of the given file, even if it is already complete, in
85
+ * which case it is uploaded again from scratch. A file that is already
86
+ * uploading or queued is ignored.
87
+ * @param {UploadFile} file
88
+ */
89
+ startUpload(file) {
90
+ this._queueFileUpload(file);
91
+ }
92
+
93
+ /**
94
+ * Override method from `UploadManager` to not restart the upload of a
95
+ * file that is already uploading or queued, like the component
96
+ * historically does; only the `upload-retry` event is dispatched.
97
+ * @override
98
+ */
99
+ retryUpload(file) {
100
+ const evt = this.dispatchEvent(
101
+ new CustomEvent('upload-retry', {
102
+ detail: { file, xhr: file.xhr },
103
+ cancelable: true,
104
+ }),
105
+ );
106
+ if (evt) {
107
+ this._queueFileUpload(file);
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Override method from `UploadManager` to treat all files as managed:
113
+ * files that are not in the `files` list are uploaded without being added
114
+ * to it, and removing a file in an `upload-before` or `upload-request`
115
+ * listener does not cancel its upload.
116
+ * @override
117
+ */
118
+ _isFileManaged(_file) {
119
+ return true;
120
+ }
121
+
122
+ /**
123
+ * Override method from `UploadManager` to leave the state of a file whose
124
+ * `upload-before` or `upload-request` event was prevented untouched, so
125
+ * that the preventing listener can take over the request (e.g. send the
126
+ * xhr manually). The upload slot stays taken until the taken-over request
127
+ * completes.
128
+ * @override
129
+ */
130
+ _holdFile(_file) {
131
+ // The listener that prevented the upload is expected to take it over
132
+ }
133
+
134
+ /**
135
+ * Override method from `UploadManager` to keep the progress properties of
136
+ * the previous upload attempt until a new upload progresses.
137
+ * @override
138
+ */
139
+ _resetFileProgress(_file) {
140
+ // Progress is only updated by upload progress events
141
+ }
142
+
143
+ /**
144
+ * Override method from `UploadManager` to keep the last request available
145
+ * on the file after the upload has finished, e.g. in the `upload-retry`
146
+ * event detail.
147
+ * @override
148
+ */
149
+ _clearFileXhr(_file) {
150
+ // The request reference is kept on the file
151
+ }
152
+
153
+ /**
154
+ * Override method from `UploadManager` to also free upload capacity for
155
+ * other queued files when a file is removed.
156
+ * @override
157
+ */
158
+ _removeFile(file) {
159
+ super._removeFile(file);
160
+ this._processUploadQueue();
161
+ }
162
+ }
163
+
164
+ // Define the configuration properties as getters that read the current value
165
+ // from the host component. The setters are no-ops so that the assignments in
166
+ // the `UploadManager` constructor are ignored.
167
+ Object.entries(MANAGER_CONFIG).forEach(([prop, getValue]) => {
168
+ Object.defineProperty(InternalUploadManager.prototype, prop, {
169
+ get() {
170
+ return getValue(this.__host);
171
+ },
172
+ set(_value) {},
173
+ });
174
+ });
@@ -10,12 +10,7 @@ export type UploadFormat = 'raw' | 'multipart';
10
10
  export type FileRejectError = 'tooManyFiles' | 'fileIsTooBig' | 'incorrectFileType';
11
11
 
12
12
  export type UploadErrorKey =
13
- | 'timeout'
14
- | 'serverUnavailable'
15
- | 'unexpectedServerError'
16
- | 'forbidden'
17
- | 'sendFailed'
18
- | 'fileTooLarge';
13
+ 'timeout' | 'serverUnavailable' | 'unexpectedServerError' | 'forbidden' | 'sendFailed' | 'fileTooLarge';
19
14
 
20
15
  export interface UploadFile extends File {
21
16
  uploadTarget: string;