@vaadin/upload 25.1.0-beta1 → 25.1.0-beta3

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.
@@ -28,23 +28,20 @@ export const uploadFileStyles = [
28
28
  display: none;
29
29
  }
30
30
 
31
- /* Hide thumbnail by default, only show with thumbnails theme */
32
31
  [part='thumbnail'],
33
32
  [part='loader'] {
34
33
  display: none;
35
34
  grid-column: 1;
36
35
  }
37
36
 
38
- [part='thumbnail'] {
39
- object-fit: cover;
40
- }
41
-
37
+ :host([uploading]) [part='loader'],
42
38
  [part='done-icon']:not([hidden]),
43
39
  [part='warning-icon']:not([hidden]) {
44
40
  display: flex;
45
41
  grid-column: 1;
46
42
  }
47
43
 
44
+ [part='loader']::before,
48
45
  [part='done-icon']::before,
49
46
  [part='warning-icon']::before {
50
47
  content: '\\2003' / '';
@@ -55,6 +52,10 @@ export const uploadFileStyles = [
55
52
  width: var(--vaadin-icon-size, 1lh);
56
53
  }
57
54
 
55
+ [part='loader']::before {
56
+ margin: calc(var(--vaadin-spinner-width, 2px) * -1);
57
+ }
58
+
58
59
  :is([part$='icon'], [part$='button'])::before {
59
60
  mask-size: var(--vaadin-icon-visual-size, 100%);
60
61
  mask-position: 50%;
@@ -163,48 +164,65 @@ export const uploadFileStyles = [
163
164
  /* THUMBNAILS VARIANT */
164
165
 
165
166
  :host([theme~='thumbnails']) {
166
- --_prefix-area-size: 2rem;
167
-
168
- grid-template-columns: var(--_prefix-area-size) minmax(0, 1fr) auto;
169
- grid-auto-columns: auto;
170
- grid-template-rows: auto;
171
- position: relative;
167
+ grid-template-columns: max-content 1fr max-content;
172
168
  align-items: center;
173
169
  background: var(--vaadin-background-container);
174
- gap: var(--vaadin-gap-s);
170
+ padding: 0;
171
+ contain: content;
172
+
173
+ & [part] {
174
+ grid-row: 1;
175
+ }
175
176
 
176
177
  & [part='thumbnail'],
177
- & [part='done-icon'],
178
- & [part='warning-icon'] {
179
- width: 100%;
180
- aspect-ratio: 1 / 1;
178
+ & [part$='icon'] {
179
+ grid-column: 1;
180
+ align-self: stretch;
181
+ display: flex;
181
182
  align-items: center;
182
183
  justify-content: center;
183
- grid-column: 1;
184
+ transition: 0.2s opacity linear;
185
+ background: var(--vaadin-background-container-strong);
186
+ padding: var(--vaadin-upload-file-padding, var(--vaadin-padding-s));
187
+ contain: content;
188
+
189
+ &[hidden] {
190
+ opacity: 0;
191
+ }
192
+ }
193
+
194
+ & [part='thumbnail'] > img {
195
+ object-fit: cover;
196
+ position: absolute;
197
+ width: 100%;
198
+ height: 100%;
184
199
  }
185
200
 
186
201
  & [part='loader']:not([hidden]) {
202
+ place-self: center;
187
203
  display: flex;
188
- align-self: stretch;
189
- aspect-ratio: 1 / 1;
190
204
  }
191
205
 
192
- & [part='done-icon'] {
193
- display: none;
194
-
195
- &::before {
196
- content: '';
197
- width: var(--vaadin-icon-size, 1lh);
198
- height: var(--vaadin-icon-size, 1lh);
199
- /* TODO: Replace with vaadin file icon, once it exists. */
200
- mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg>');
201
- mask-size: contain;
202
- background: currentColor;
203
- }
206
+ & [part='done-icon']::before {
207
+ background: var(--vaadin-upload-file-done-color, currentColor);
208
+ mask-image: var(--_vaadin-icon-file);
204
209
  }
205
210
 
206
- & [part='status'],
207
- & [part='error'] {
211
+ & [part='meta'] {
212
+ padding: var(--vaadin-upload-file-padding, var(--vaadin-padding-s));
213
+ padding-inline: 0;
214
+ }
215
+
216
+ & [part='name'] {
217
+ word-break: break-all;
218
+ }
219
+
220
+ & [part='commands'] {
221
+ padding: var(--vaadin-upload-padding, var(--vaadin-padding-s));
222
+ padding-inline-start: 0;
223
+ }
224
+
225
+ & [part='status'] {
208
226
  clip-path: inset(50%);
209
227
  width: 1px;
210
228
  height: 1px;
@@ -214,30 +232,34 @@ export const uploadFileStyles = [
214
232
  white-space: nowrap;
215
233
  }
216
234
 
235
+ & [part='error'] {
236
+ font-size: 0.875em;
237
+ line-height: 1.25;
238
+ }
239
+
217
240
  & ::slotted([slot='progress']) {
218
- clip-path: inset(50%);
219
- margin: 0;
220
- overflow: hidden;
241
+ grid-row: auto;
242
+ grid-column: auto;
221
243
  position: absolute;
244
+ inset: 0;
245
+ opacity: 0.3;
246
+ pointer-events: none;
247
+ --vaadin-progress-bar-height: auto;
248
+ --vaadin-progress-bar-border-width: 0px;
249
+ --vaadin-progress-bar-border-radius: 0px;
250
+ --vaadin-progress-bar-background: transparent;
222
251
  }
223
- }
224
-
225
- :host([theme~='thumbnails'][complete]) {
226
- & [part='thumbnail'] {
227
- &:not([hidden]) {
228
- display: block;
229
-
230
- & + [part='done-icon'] {
231
- display: none;
232
- }
233
- }
234
252
 
235
- &[hidden] + [part='done-icon'] {
236
- display: flex;
237
- }
253
+ & ::slotted([slot='progress'][indeterminate]) {
254
+ opacity: 0;
238
255
  }
239
256
  }
240
257
 
258
+ :host([theme~='thumbnails']:not([complete])) [part='thumbnail'],
259
+ :host([theme~='thumbnails'][complete]) [part='thumbnail']:not([hidden]) + [part='done-icon'] {
260
+ display: none;
261
+ }
262
+
241
263
  /* TODO: queued state styles (no attribute makes this difficult to target) */
242
264
 
243
265
  @media (forced-colors: active) {
@@ -101,7 +101,6 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
101
101
 
102
102
  /**
103
103
  * Capture attribute for mobile file input.
104
- * @type {string}
105
104
  */
106
105
  capture: {
107
106
  type: String,
@@ -109,7 +108,6 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
109
108
 
110
109
  /**
111
110
  * True when max files has been reached on the manager.
112
- * @type {boolean}
113
111
  */
114
112
  maxFilesReached: {
115
113
  type: Boolean,
@@ -81,7 +81,6 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
81
81
  /**
82
82
  * Whether the drop zone is disabled.
83
83
  * Returns true if either explicitly disabled, manager is disabled, or no manager is set.
84
- * @type {boolean}
85
84
  */
86
85
  disabled: {
87
86
  type: Boolean,
@@ -90,7 +89,6 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
90
89
 
91
90
  /**
92
91
  * True when max files has been reached on the manager.
93
- * @type {boolean}
94
92
  * @readonly
95
93
  */
96
94
  maxFilesReached: {
@@ -96,6 +96,10 @@ export interface UploadFileEventMap extends HTMLElementEventMap, UploadFileCusto
96
96
  * `--vaadin-upload-file-warning-color` |
97
97
  *
98
98
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
99
+ *
100
+ * @fires {CustomEvent} file-abort - Fired when the abort button is pressed.
101
+ * @fires {CustomEvent} file-retry - Fired when the retry button is pressed.
102
+ * @fires {CustomEvent} file-start - Fired when the start button is pressed.
99
103
  */
100
104
  declare class UploadFile extends UploadFileMixin(ThemableMixin(HTMLElement)) {
101
105
  addEventListener<K extends keyof UploadFileEventMap>(
@@ -77,6 +77,10 @@ import { UploadFileMixin } from './vaadin-upload-file-mixin.js';
77
77
  *
78
78
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
79
79
  *
80
+ * @fires {CustomEvent} file-abort - Fired when the abort button is pressed.
81
+ * @fires {CustomEvent} file-retry - Fired when the retry button is pressed.
82
+ * @fires {CustomEvent} file-start - Fired when the start button is pressed.
83
+ *
80
84
  * @customElement vaadin-upload-file
81
85
  * @extends HTMLElement
82
86
  * @mixes UploadFileMixin
@@ -102,7 +106,12 @@ class UploadFile extends UploadFileMixin(ThemableMixin(PolylitMixin(LumoInjectio
102
106
 
103
107
  return html`
104
108
  <div part="loader" ?hidden="${!this.uploading}" aria-hidden="true"></div>
105
- <img src="${this.__thumbnail}" alt="${this.fileName}" part="thumbnail" ?hidden="${!this.__thumbnail}" />
109
+
110
+ ${this.__thumbnail
111
+ ? html`<div part="thumbnail">
112
+ <img src="${this.__thumbnail}" alt="${this.fileName}" />
113
+ </div>`
114
+ : nothing}
106
115
 
107
116
  <div part="done-icon" ?hidden="${!this.complete}" aria-hidden="true"></div>
108
117
  <div part="warning-icon" ?hidden="${!this.errorMessage}" aria-hidden="true"></div>
@@ -273,7 +273,6 @@ export declare class UploadMixinClass {
273
273
  * }
274
274
  * ```
275
275
  *
276
- * @type {!UploadI18n}
277
276
  * @default {English}
278
277
  */
279
278
  i18n: UploadI18n;
@@ -114,7 +114,6 @@ export const UploadMixin = (superClass) =>
114
114
  return {
115
115
  /**
116
116
  * If true, the user cannot interact with this element.
117
- * @type {boolean}
118
117
  */
119
118
  disabled: {
120
119
  type: Boolean,
@@ -129,7 +128,6 @@ export const UploadMixin = (superClass) =>
129
128
  * it false means that drop is enabled even in touch-devices, and true
130
129
  * disables drop in all devices.
131
130
  *
132
- * @type {boolean}
133
131
  * @default true in touch-devices, false otherwise.
134
132
  */
135
133
  nodrop: {
@@ -141,7 +139,6 @@ export const UploadMixin = (superClass) =>
141
139
  /**
142
140
  * The server URL. The default value is an empty string, which means that
143
141
  * _window.location_ will be used.
144
- * @type {string}
145
142
  */
146
143
  target: {
147
144
  type: String,
@@ -150,7 +147,6 @@ export const UploadMixin = (superClass) =>
150
147
 
151
148
  /**
152
149
  * HTTP Method used to send the files. Only POST and PUT are allowed.
153
- * @type {!UploadMethod}
154
150
  */
155
151
  method: {
156
152
  type: String,
@@ -173,7 +169,6 @@ export const UploadMixin = (superClass) =>
173
169
  /**
174
170
  * Max time in milliseconds for the entire upload process, if exceeded the
175
171
  * request will be aborted. Zero means that there is no timeout.
176
- * @type {number}
177
172
  */
178
173
  timeout: {
179
174
  type: Number,
@@ -221,7 +216,6 @@ export const UploadMixin = (superClass) =>
221
216
  * Limit of files to upload, by default it is unlimited. If the value is
222
217
  * set to one, native file browser will prevent selecting multiple files.
223
218
  * @attr {number} max-files
224
- * @type {number}
225
219
  */
226
220
  maxFiles: {
227
221
  type: Number,
@@ -232,7 +226,6 @@ export const UploadMixin = (superClass) =>
232
226
  /**
233
227
  * Specifies if the maximum number of files have been uploaded
234
228
  * @attr {boolean} max-files-reached
235
- * @type {boolean}
236
229
  */
237
230
  maxFilesReached: {
238
231
  type: Boolean,
@@ -249,7 +242,6 @@ export const UploadMixin = (superClass) =>
249
242
  * Notice that MIME types are widely supported, while file extensions
250
243
  * are only implemented in certain browsers, so avoid using it.
251
244
  * Example: accept="video/*,image/tiff" or accept=".pdf,audio/mp3"
252
- * @type {string}
253
245
  */
254
246
  accept: {
255
247
  type: String,
@@ -262,7 +254,6 @@ export const UploadMixin = (superClass) =>
262
254
  * sending the request. Obviously you need to do the same validation in
263
255
  * the server-side and be sure that they are aligned.
264
256
  * @attr {number} max-file-size
265
- * @type {number}
266
257
  */
267
258
  maxFileSize: {
268
259
  type: Number,
@@ -284,7 +275,6 @@ export const UploadMixin = (superClass) =>
284
275
  * Specifies the 'name' property at Content-Disposition for multipart uploads.
285
276
  * This property is ignored when uploadFormat is 'raw'.
286
277
  * @attr {string} form-data-name
287
- * @type {string}
288
278
  */
289
279
  formDataName: {
290
280
  type: String,
@@ -295,7 +285,6 @@ export const UploadMixin = (superClass) =>
295
285
  * Prevents upload(s) from immediately uploading upon adding file(s).
296
286
  * When set, you must manually trigger uploads using the `uploadFiles` method
297
287
  * @attr {boolean} no-auto
298
- * @type {boolean}
299
288
  */
300
289
  noAuto: {
301
290
  type: Boolean,
@@ -305,7 +294,6 @@ export const UploadMixin = (superClass) =>
305
294
  /**
306
295
  * Set the withCredentials flag on the request.
307
296
  * @attr {boolean} with-credentials
308
- * @type {boolean}
309
297
  */
310
298
  withCredentials: {
311
299
  type: Boolean,
@@ -317,7 +305,6 @@ export const UploadMixin = (superClass) =>
317
305
  * - 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default)
318
306
  * - 'multipart': Send file using multipart/form-data encoding
319
307
  * @attr {string} upload-format
320
- * @type {string}
321
308
  */
322
309
  uploadFormat: {
323
310
  type: String,
@@ -330,7 +317,6 @@ export const UploadMixin = (superClass) =>
330
317
  * uploading large numbers of files. Files exceeding this limit will be queued
331
318
  * and uploaded as active uploads complete.
332
319
  * @attr {number} max-concurrent-uploads
333
- * @type {number}
334
320
  */
335
321
  maxConcurrentUploads: {
336
322
  type: Number,
@@ -342,7 +328,9 @@ export const UploadMixin = (superClass) =>
342
328
  * Pass-through to input's capture attribute. Allows user to trigger device inputs
343
329
  * such as camera or microphone immediately.
344
330
  */
345
- capture: String,
331
+ capture: {
332
+ type: String,
333
+ },
346
334
 
347
335
  /** @private */
348
336
  _addButton: {
@@ -443,7 +431,7 @@ export const UploadMixin = (superClass) =>
443
431
  * }
444
432
  * }
445
433
  * ```
446
- * @return {!UploadI18n}
434
+ * @type {!UploadI18n}
447
435
  */
448
436
  get i18n() {
449
437
  return super.i18n;
@@ -77,6 +77,11 @@ export type UploadRetryEvent = UploadEvent<{ xhr: XMLHttpRequest; file: UploadFi
77
77
  */
78
78
  export type UploadAbortEvent = UploadEvent<{ xhr: XMLHttpRequest; file: UploadFile }>;
79
79
 
80
+ /**
81
+ * Fired when a file is removed from the list.
82
+ */
83
+ export type UploadFileRemoveEvent = UploadEvent<{ file: UploadFile }>;
84
+
80
85
  /**
81
86
  * Fired when the XHR has been opened but not sent yet. Useful for appending
82
87
  * data keys to the FormData object, for changing some parameters like
@@ -94,6 +99,8 @@ export type UploadRequestEvent = UploadEvent<{
94
99
  export interface UploadCustomEventMap {
95
100
  'file-reject': UploadFileRejectEvent;
96
101
 
102
+ 'file-remove': UploadFileRemoveEvent;
103
+
97
104
  'files-changed': UploadFilesChangedEvent;
98
105
 
99
106
  'max-files-reached-changed': UploadMaxFilesReachedChangedEvent;
@@ -191,6 +198,7 @@ export interface UploadEventMap extends HTMLElementEventMap, UploadCustomEventMa
191
198
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
192
199
  *
193
200
  * @fires {CustomEvent} file-reject - Fired when a file cannot be added to the queue due to a constrain.
201
+ * @fires {CustomEvent} file-remove - Fired when a file is removed from the list.
194
202
  * @fires {CustomEvent} files-changed - Fired when the `files` property changes.
195
203
  * @fires {CustomEvent} max-files-reached-changed - Fired when the `maxFilesReached` property changes.
196
204
  * @fires {CustomEvent} upload-before - Fired before the XHR is opened.
@@ -89,6 +89,7 @@ import { UploadMixin } from './vaadin-upload-mixin.js';
89
89
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
90
90
  *
91
91
  * @fires {CustomEvent} file-reject - Fired when a file cannot be added to the queue due to a constrain.
92
+ * @fires {CustomEvent} file-remove - Fired when a file is removed from the list.
92
93
  * @fires {CustomEvent} files-changed - Fired when the `files` property changes.
93
94
  * @fires {CustomEvent} max-files-reached-changed - Fired when the `maxFilesReached` property changes.
94
95
  * @fires {CustomEvent} upload-before - Fired before the XHR is opened.