@vaadin/upload 25.0.0-beta2 → 25.0.0-beta4

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.0.0-beta2",
3
+ "version": "25.0.0-beta4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,23 +34,23 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "@open-wc/dedupe-mixin": "^1.3.0",
37
- "@vaadin/a11y-base": "25.0.0-beta2",
38
- "@vaadin/button": "25.0.0-beta2",
39
- "@vaadin/component-base": "25.0.0-beta2",
40
- "@vaadin/progress-bar": "25.0.0-beta2",
41
- "@vaadin/vaadin-themable-mixin": "25.0.0-beta2",
37
+ "@vaadin/a11y-base": "25.0.0-beta4",
38
+ "@vaadin/button": "25.0.0-beta4",
39
+ "@vaadin/component-base": "25.0.0-beta4",
40
+ "@vaadin/progress-bar": "25.0.0-beta4",
41
+ "@vaadin/vaadin-themable-mixin": "25.0.0-beta4",
42
42
  "lit": "^3.0.0"
43
43
  },
44
44
  "devDependencies": {
45
- "@vaadin/chai-plugins": "25.0.0-beta2",
46
- "@vaadin/test-runner-commands": "25.0.0-beta2",
45
+ "@vaadin/chai-plugins": "25.0.0-beta4",
46
+ "@vaadin/test-runner-commands": "25.0.0-beta4",
47
47
  "@vaadin/testing-helpers": "^2.0.0",
48
- "@vaadin/vaadin-lumo-styles": "25.0.0-beta2",
48
+ "@vaadin/vaadin-lumo-styles": "25.0.0-beta4",
49
49
  "sinon": "^21.0.0"
50
50
  },
51
51
  "web-types": [
52
52
  "web-types.json",
53
53
  "web-types.lit.json"
54
54
  ],
55
- "gitHead": "e078f8371ae266f05c7ca1ec25686cc489c83f24"
55
+ "gitHead": "707c30af7ed0afacc13c0afb27d047b043160d1f"
56
56
  }
@@ -90,11 +90,7 @@ export const uploadFileStyles = css`
90
90
  color: var(--vaadin-upload-file-button-text-color, var(--vaadin-text-color));
91
91
  cursor: var(--vaadin-clickable-cursor);
92
92
  flex-shrink: 0;
93
- font-family: var(--vaadin-upload-file-button-font-family, inherit);
94
- font-size: var(--vaadin-upload-file-button-font-size, inherit);
95
- font-weight: var(--vaadin-upload-file-button-font-weight, 500);
96
- height: var(--vaadin-upload-file-button-height, auto);
97
- line-height: var(--vaadin-upload-file-button-line-height, inherit);
93
+ font: inherit;
98
94
  padding: var(--vaadin-upload-file-button-padding, var(--vaadin-padding-container));
99
95
  }
100
96
 
@@ -62,9 +62,7 @@ class UploadFile extends UploadFileMixin(ThemableMixin(PolylitMixin(LumoInjectio
62
62
  }
63
63
 
64
64
  static get lumoInjector() {
65
- return {
66
- includeBaseStyles: true,
67
- };
65
+ return { ...super.lumoInjector, includeBaseStyles: true };
68
66
  }
69
67
 
70
68
  /** @protected */
@@ -26,9 +26,7 @@ class UploadIcon extends ThemableMixin(LumoInjectionMixin(LitElement)) {
26
26
  }
27
27
 
28
28
  static get lumoInjector() {
29
- return {
30
- includeBaseStyles: true,
31
- };
29
+ return { ...super.lumoInjector, includeBaseStyles: true };
32
30
  }
33
31
 
34
32
  /** @protected */
@@ -68,6 +68,8 @@ export interface UploadI18n {
68
68
 
69
69
  export type UploadMethod = 'POST' | 'PUT';
70
70
 
71
+ export type UploadFormat = 'raw' | 'multipart';
72
+
71
73
  export declare function UploadMixin<T extends Constructor<HTMLElement>>(
72
74
  base: T,
73
75
  ): Constructor<UploadMixinClass> & Constructor<I18nMixinClass<UploadI18n>> & T;
@@ -170,7 +172,8 @@ export declare class UploadMixinClass {
170
172
  maxFileSize: number;
171
173
 
172
174
  /**
173
- * Specifies the 'name' property at Content-Disposition
175
+ * Specifies the 'name' property at Content-Disposition for multipart uploads.
176
+ * This property is ignored when uploadFormat is 'raw'.
174
177
  * @attr {string} form-data-name
175
178
  */
176
179
  formDataName: string;
@@ -194,6 +197,14 @@ export declare class UploadMixinClass {
194
197
  */
195
198
  capture: string | null | undefined;
196
199
 
200
+ /**
201
+ * Specifies the upload format to use when sending files to the server.
202
+ * - 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default)
203
+ * - 'multipart': Send file using multipart/form-data encoding
204
+ * @attr {string} upload-format
205
+ */
206
+ uploadFormat: UploadFormat;
207
+
197
208
  /**
198
209
  * The object used to localize this component. To change the default
199
210
  * localization, replace this with an object that provides all properties, or
@@ -279,7 +279,8 @@ export const UploadMixin = (superClass) =>
279
279
  },
280
280
 
281
281
  /**
282
- * Specifies the 'name' property at Content-Disposition
282
+ * Specifies the 'name' property at Content-Disposition for multipart uploads.
283
+ * This property is ignored when uploadFormat is 'raw'.
283
284
  * @attr {string} form-data-name
284
285
  * @type {string}
285
286
  */
@@ -309,6 +310,18 @@ export const UploadMixin = (superClass) =>
309
310
  value: false,
310
311
  },
311
312
 
313
+ /**
314
+ * Specifies the upload format to use when sending files to the server.
315
+ * - 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default)
316
+ * - 'multipart': Send file using multipart/form-data encoding
317
+ * @attr {string} upload-format
318
+ * @type {string}
319
+ */
320
+ uploadFormat: {
321
+ type: String,
322
+ value: 'raw',
323
+ },
324
+
312
325
  /**
313
326
  * Pass-through to input's capture attribute. Allows user to trigger device inputs
314
327
  * such as camera or microphone immediately.
@@ -636,7 +649,7 @@ export const UploadMixin = (superClass) =>
636
649
  }
637
650
 
638
651
  /** @private */
639
- _configureXhr(xhr) {
652
+ _configureXhr(xhr, file = null, isRawUpload = false) {
640
653
  if (typeof this.headers === 'string') {
641
654
  try {
642
655
  this.headers = JSON.parse(this.headers);
@@ -647,6 +660,13 @@ export const UploadMixin = (superClass) =>
647
660
  Object.entries(this.headers).forEach(([key, value]) => {
648
661
  xhr.setRequestHeader(key, value);
649
662
  });
663
+
664
+ // Set Content-Type and filename header for raw binary uploads
665
+ if (isRawUpload && file) {
666
+ xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream');
667
+ xhr.setRequestHeader('X-Filename', encodeURIComponent(file.name));
668
+ }
669
+
650
670
  if (this.timeout) {
651
671
  xhr.timeout = this.timeout;
652
672
  }
@@ -759,12 +779,17 @@ export const UploadMixin = (superClass) =>
759
779
  }
760
780
  };
761
781
 
762
- const formData = new FormData();
782
+ // Determine upload format and prepare request body
783
+ const isRawUpload = this.uploadFormat === 'raw';
763
784
 
764
785
  if (!file.uploadTarget) {
765
786
  file.uploadTarget = this.target || '';
766
787
  }
767
- file.formDataName = this.formDataName;
788
+
789
+ // Only set formDataName for multipart uploads
790
+ if (!isRawUpload) {
791
+ file.formDataName = this.formDataName;
792
+ }
768
793
 
769
794
  const evt = this.dispatchEvent(
770
795
  new CustomEvent('upload-before', {
@@ -776,10 +801,19 @@ export const UploadMixin = (superClass) =>
776
801
  return;
777
802
  }
778
803
 
779
- formData.append(file.formDataName, file, file.name);
804
+ let requestBody;
805
+ if (isRawUpload) {
806
+ // Raw binary upload - send file directly
807
+ requestBody = file;
808
+ } else {
809
+ // Multipart upload - use FormData
810
+ const formData = new FormData();
811
+ formData.append(file.formDataName, file, file.name);
812
+ requestBody = formData;
813
+ }
780
814
 
781
815
  xhr.open(this.method, file.uploadTarget, true);
782
- this._configureXhr(xhr);
816
+ this._configureXhr(xhr, file, isRawUpload);
783
817
 
784
818
  file.status = this.__effectiveI18n.uploading.status.connecting;
785
819
  file.uploading = file.indeterminate = true;
@@ -796,14 +830,26 @@ export const UploadMixin = (superClass) =>
796
830
 
797
831
  // Custom listener could modify the xhr just before sending it
798
832
  // preventing default
833
+ const eventDetail = {
834
+ file,
835
+ xhr,
836
+ uploadFormat: this.uploadFormat,
837
+ requestBody,
838
+ };
839
+
840
+ // Expose formData property when using multipart so listeners can modify it
841
+ if (!isRawUpload) {
842
+ eventDetail.formData = requestBody;
843
+ }
844
+
799
845
  const uploadEvt = this.dispatchEvent(
800
846
  new CustomEvent('upload-request', {
801
- detail: { file, xhr, formData },
847
+ detail: eventDetail,
802
848
  cancelable: true,
803
849
  }),
804
850
  );
805
851
  if (uploadEvt) {
806
- xhr.send(formData);
852
+ xhr.send(requestBody);
807
853
  }
808
854
  }
809
855
 
@@ -5,9 +5,9 @@
5
5
  */
6
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
7
7
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
- import { type UploadFile, UploadMixin } from './vaadin-upload-mixin.js';
8
+ import { type UploadFile, type UploadFormat, UploadMixin } from './vaadin-upload-mixin.js';
9
9
 
10
- export { UploadFile, UploadI18n, UploadMethod } from './vaadin-upload-mixin.js';
10
+ export { UploadFile, UploadFormat, UploadI18n, UploadMethod } from './vaadin-upload-mixin.js';
11
11
 
12
12
  type UploadEvent<T> = CustomEvent<T> & { target: Upload };
13
13
 
@@ -83,7 +83,13 @@ export type UploadAbortEvent = UploadEvent<{ xhr: XMLHttpRequest; file: UploadFi
83
83
  * headers, etc. If the event is defaultPrevented, `vaadin-upload` will not
84
84
  * send the request allowing the user to do something on his own.
85
85
  */
86
- export type UploadRequestEvent = UploadEvent<{ xhr: XMLHttpRequest; file: UploadFile; formData: FormData }>;
86
+ export type UploadRequestEvent = UploadEvent<{
87
+ xhr: XMLHttpRequest;
88
+ file: UploadFile;
89
+ uploadFormat: UploadFormat;
90
+ requestBody: FormData | File;
91
+ formData?: FormData;
92
+ }>;
87
93
 
88
94
  export interface UploadCustomEventMap {
89
95
  'file-reject': UploadFileRejectEvent;
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/upload",
4
- "version": "25.0.0-beta2",
4
+ "version": "25.0.0-beta4",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -339,7 +339,7 @@
339
339
  },
340
340
  {
341
341
  "name": "form-data-name",
342
- "description": "Specifies the 'name' property at Content-Disposition",
342
+ "description": "Specifies the 'name' property at Content-Disposition for multipart uploads.\nThis property is ignored when uploadFormat is 'raw'.",
343
343
  "value": {
344
344
  "type": [
345
345
  "string"
@@ -364,6 +364,15 @@
364
364
  ]
365
365
  }
366
366
  },
367
+ {
368
+ "name": "upload-format",
369
+ "description": "Specifies the upload format to use when sending files to the server.\n- 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default)\n- 'multipart': Send file using multipart/form-data encoding",
370
+ "value": {
371
+ "type": [
372
+ "string"
373
+ ]
374
+ }
375
+ },
367
376
  {
368
377
  "name": "capture",
369
378
  "description": "Pass-through to input's capture attribute. Allows user to trigger device inputs\nsuch as camera or microphone immediately.",
@@ -491,7 +500,7 @@
491
500
  },
492
501
  {
493
502
  "name": "formDataName",
494
- "description": "Specifies the 'name' property at Content-Disposition",
503
+ "description": "Specifies the 'name' property at Content-Disposition for multipart uploads.\nThis property is ignored when uploadFormat is 'raw'.",
495
504
  "value": {
496
505
  "type": [
497
506
  "string"
@@ -516,6 +525,15 @@
516
525
  ]
517
526
  }
518
527
  },
528
+ {
529
+ "name": "uploadFormat",
530
+ "description": "Specifies the upload format to use when sending files to the server.\n- 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default)\n- 'multipart': Send file using multipart/form-data encoding",
531
+ "value": {
532
+ "type": [
533
+ "string"
534
+ ]
535
+ }
536
+ },
519
537
  {
520
538
  "name": "capture",
521
539
  "description": "Pass-through to input's capture attribute. Allows user to trigger device inputs\nsuch as camera or microphone immediately.",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/upload",
4
- "version": "25.0.0-beta2",
4
+ "version": "25.0.0-beta4",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -217,7 +217,14 @@
217
217
  },
218
218
  {
219
219
  "name": ".formDataName",
220
- "description": "Specifies the 'name' property at Content-Disposition",
220
+ "description": "Specifies the 'name' property at Content-Disposition for multipart uploads.\nThis property is ignored when uploadFormat is 'raw'.",
221
+ "value": {
222
+ "kind": "expression"
223
+ }
224
+ },
225
+ {
226
+ "name": ".uploadFormat",
227
+ "description": "Specifies the upload format to use when sending files to the server.\n- 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default)\n- 'multipart': Send file using multipart/form-data encoding",
221
228
  "value": {
222
229
  "kind": "expression"
223
230
  }