@vaadin/upload 25.1.0-alpha9 → 25.1.0-beta2

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.
@@ -5,176 +5,267 @@
5
5
  */
6
6
  import '@vaadin/component-base/src/styles/style-props.js';
7
7
  import { css } from 'lit';
8
+ import { loaderStyles } from '@vaadin/component-base/src/styles/loader-styles.js';
9
+
10
+ export const uploadFileStyles = [
11
+ loaderStyles,
12
+ css`
13
+ :host {
14
+ align-items: baseline;
15
+ display: grid;
16
+ gap: var(--vaadin-upload-file-gap, var(--vaadin-gap-s));
17
+ grid-template-columns: var(--vaadin-icon-size, 1lh) minmax(0, 1fr) auto;
18
+ padding: var(--vaadin-upload-file-padding, var(--vaadin-padding-s));
19
+ border-radius: var(--vaadin-upload-file-border-radius, var(--vaadin-radius-m));
20
+ }
21
+
22
+ :host(:focus-visible) {
23
+ outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
24
+ outline-offset: calc(var(--vaadin-focus-ring-width) * -1);
25
+ }
26
+
27
+ [hidden] {
28
+ display: none;
29
+ }
30
+
31
+ [part='thumbnail'],
32
+ [part='loader'] {
33
+ display: none;
34
+ grid-column: 1;
35
+ }
36
+
37
+ :host([uploading]) [part='loader'],
38
+ [part='done-icon']:not([hidden]),
39
+ [part='warning-icon']:not([hidden]) {
40
+ display: flex;
41
+ grid-column: 1;
42
+ }
43
+
44
+ [part='loader']::before,
45
+ [part='done-icon']::before,
46
+ [part='warning-icon']::before {
47
+ content: '\\2003' / '';
48
+ display: inline-flex;
49
+ align-items: center;
50
+ flex: none;
51
+ height: var(--vaadin-icon-size, 1lh);
52
+ width: var(--vaadin-icon-size, 1lh);
53
+ }
54
+
55
+ [part='loader']::before {
56
+ margin: calc(var(--vaadin-spinner-width, 2px) * -1);
57
+ }
8
58
 
9
- export const uploadFileStyles = css`
10
- :host {
11
- align-items: baseline;
12
- display: grid;
13
- gap: var(--vaadin-upload-file-gap, var(--vaadin-gap-s));
14
- grid-template-columns: var(--vaadin-icon-size, 1lh) minmax(0, 1fr) auto;
15
- padding: var(--vaadin-upload-file-padding, var(--vaadin-padding-s));
16
- border-radius: var(--vaadin-upload-file-border-radius, var(--vaadin-radius-m));
17
- }
18
-
19
- :host(:focus-visible) {
20
- outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
21
- outline-offset: calc(var(--vaadin-focus-ring-width) * -1);
22
- }
23
-
24
- [hidden] {
25
- display: none;
26
- }
27
-
28
- /* Hide thumbnail and file-icon by default, only show with thumbnails theme */
29
- [part='thumbnail'],
30
- [part='file-icon'] {
31
- display: none;
32
- }
33
-
34
- :host([theme~='thumbnails']) {
35
- grid-template-columns: 3rem minmax(0, 1fr) auto;
36
- }
37
-
38
- :host([theme~='thumbnails']) [part='thumbnail']:not([hidden]),
39
- :host([theme~='thumbnails']) [part='file-icon']:not([hidden]) {
40
- display: block;
41
- width: 3rem;
42
- height: 3rem;
43
- align-self: center;
44
- }
45
-
46
- [part='thumbnail'] {
47
- object-fit: cover;
48
- }
49
-
50
- [part='file-icon'] {
51
- background: #e0e0e0;
52
- }
53
-
54
- [part='done-icon']:not([hidden]),
55
- [part='warning-icon']:not([hidden]) {
56
- display: flex;
57
- }
58
-
59
- :host([theme~='thumbnails']) [part='done-icon'],
60
- :host([theme~='thumbnails']) [part='warning-icon'] {
61
- display: none !important;
62
- }
63
-
64
- [part='done-icon']::before,
65
- [part='warning-icon']::before {
66
- content: '\\2003' / '';
67
- display: inline-flex;
68
- align-items: center;
69
- flex: none;
70
- height: var(--vaadin-icon-size, 1lh);
71
- width: var(--vaadin-icon-size, 1lh);
72
- }
73
-
74
- :is([part$='icon'], [part$='button'])::before {
75
- mask-size: var(--vaadin-icon-visual-size, 100%);
76
- mask-position: 50%;
77
- mask-repeat: no-repeat;
78
- }
79
-
80
- [part='done-icon']::before {
81
- background: var(--vaadin-upload-file-done-color, currentColor);
82
- mask-image: var(--_vaadin-icon-checkmark);
83
- }
84
-
85
- [part='warning-icon']::before {
86
- background: var(--vaadin-upload-file-warning-color, currentColor);
87
- mask-image: var(--_vaadin-icon-warn);
88
- }
89
-
90
- [part='meta'] {
91
- grid-column: 2;
92
- }
93
-
94
- [part='name'] {
95
- color: var(--vaadin-upload-file-name-color, var(--vaadin-text-color));
96
- font-size: var(--vaadin-upload-file-name-font-size, inherit);
97
- font-weight: var(--vaadin-upload-file-name-font-weight, inherit);
98
- line-height: var(--vaadin-upload-file-name-line-height, inherit);
99
- overflow: hidden;
100
- text-overflow: ellipsis;
101
- }
102
-
103
- [part='status'] {
104
- color: var(--vaadin-upload-file-status-color, var(--vaadin-text-color-secondary));
105
- font-size: var(--vaadin-upload-file-status-font-size, inherit);
106
- font-weight: var(--vaadin-upload-file-status-font-weight, inherit);
107
- line-height: var(--vaadin-upload-file-status-line-height, inherit);
108
- }
109
-
110
- [part='error'] {
111
- color: var(--vaadin-upload-file-error-color, var(--vaadin-text-color));
112
- font-size: var(--vaadin-upload-file-error-font-size, inherit);
113
- font-weight: var(--vaadin-upload-file-error-font-weight, inherit);
114
- line-height: var(--vaadin-upload-file-error-line-height, inherit);
115
- }
116
-
117
- [part='commands'] {
118
- display: flex;
119
- align-items: center;
120
- gap: var(--vaadin-gap-xs);
121
- height: var(--vaadin-icon-size, 1lh);
122
- align-self: center;
123
- }
124
-
125
- button {
126
- background: var(--vaadin-upload-file-button-background, transparent);
127
- border: var(--vaadin-upload-file-button-border-width, 0) solid
128
- var(--vaadin-upload-file-button-border-color, var(--vaadin-border-color-secondary));
129
- border-radius: var(--vaadin-upload-file-button-border-radius, var(--vaadin-radius-m));
130
- color: var(--vaadin-upload-file-button-text-color, var(--vaadin-text-color));
131
- cursor: var(--vaadin-clickable-cursor);
132
- flex-shrink: 0;
133
- font: inherit;
134
- /* Ensure minimum click target (WCAG) */
135
- padding: var(--vaadin-upload-file-button-padding, max(0px, (24px - var(--vaadin-icon-size, 1lh)) / 2));
136
- }
137
-
138
- button:focus-visible {
139
- outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
140
- }
141
-
142
- [part='start-button']::before,
143
- [part='retry-button']::before,
144
- [part='remove-button']::before {
145
- background: currentColor;
146
- content: '\\2003' / '';
147
- display: flex;
148
- align-items: center;
149
- height: var(--vaadin-icon-size, 1lh);
150
- width: var(--vaadin-icon-size, 1lh);
151
- }
152
-
153
- [part='start-button']::before {
154
- mask-image: var(--_vaadin-icon-play);
155
- }
156
-
157
- [part='retry-button']::before {
158
- mask-image: var(--_vaadin-icon-refresh);
159
- }
160
-
161
- [part='remove-button']::before {
162
- mask-image: var(--_vaadin-icon-cross);
163
- }
164
-
165
- ::slotted([slot='progress']) {
166
- grid-column: 2 / -1;
167
- width: auto;
168
- }
169
-
170
- :host([complete]) ::slotted([slot='progress']),
171
- :host([error]) ::slotted([slot='progress']) {
172
- display: none;
173
- }
174
-
175
- @media (forced-colors: active) {
176
59
  :is([part$='icon'], [part$='button'])::before {
177
- background: CanvasText;
60
+ mask-size: var(--vaadin-icon-visual-size, 100%);
61
+ mask-position: 50%;
62
+ mask-repeat: no-repeat;
63
+ }
64
+
65
+ [part='done-icon']::before {
66
+ background: var(--vaadin-upload-file-done-color, currentColor);
67
+ mask-image: var(--_vaadin-icon-checkmark);
68
+ }
69
+
70
+ [part='warning-icon']::before {
71
+ background: var(--vaadin-upload-file-warning-color, currentColor);
72
+ mask-image: var(--_vaadin-icon-warn);
73
+ }
74
+
75
+ [part='meta'] {
76
+ grid-column: 2;
77
+
78
+ & > div {
79
+ cursor: inherit;
80
+ }
81
+ }
82
+
83
+ [part='name'] {
84
+ color: var(--vaadin-upload-file-name-color, var(--vaadin-text-color));
85
+ font-size: var(--vaadin-upload-file-name-font-size, inherit);
86
+ font-weight: var(--vaadin-upload-file-name-font-weight, inherit);
87
+ line-height: var(--vaadin-upload-file-name-line-height, inherit);
88
+ overflow: hidden;
89
+ text-overflow: ellipsis;
90
+ }
91
+
92
+ [part='status'] {
93
+ color: var(--vaadin-upload-file-status-color, var(--vaadin-text-color-secondary));
94
+ font-size: var(--vaadin-upload-file-status-font-size, inherit);
95
+ font-weight: var(--vaadin-upload-file-status-font-weight, inherit);
96
+ line-height: var(--vaadin-upload-file-status-line-height, inherit);
97
+ }
98
+
99
+ [part='error'] {
100
+ color: var(--vaadin-upload-file-error-color, var(--vaadin-text-color));
101
+ font-size: var(--vaadin-upload-file-error-font-size, inherit);
102
+ font-weight: var(--vaadin-upload-file-error-font-weight, inherit);
103
+ line-height: var(--vaadin-upload-file-error-line-height, inherit);
104
+ }
105
+
106
+ [part='commands'] {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: var(--vaadin-gap-xs);
110
+ height: var(--vaadin-icon-size, 1lh);
111
+ align-self: center;
112
+ }
113
+
114
+ button {
115
+ background: var(--vaadin-upload-file-button-background, transparent);
116
+ border: var(--vaadin-upload-file-button-border-width, 0) solid
117
+ var(--vaadin-upload-file-button-border-color, var(--vaadin-border-color-secondary));
118
+ border-radius: var(--vaadin-upload-file-button-border-radius, var(--vaadin-radius-m));
119
+ color: var(--vaadin-upload-file-button-text-color, var(--vaadin-text-color));
120
+ cursor: var(--vaadin-clickable-cursor);
121
+ flex-shrink: 0;
122
+ font: inherit;
123
+ /* Ensure minimum click target (WCAG) */
124
+ padding: var(--vaadin-upload-file-button-padding, max(0px, (24px - var(--vaadin-icon-size, 1lh)) / 2));
125
+ }
126
+
127
+ button:focus-visible {
128
+ outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
129
+ }
130
+
131
+ [part='start-button']::before,
132
+ [part='retry-button']::before,
133
+ [part='remove-button']::before {
134
+ background: currentColor;
135
+ content: '\\2003' / '';
136
+ display: flex;
137
+ align-items: center;
138
+ height: var(--vaadin-icon-size, 1lh);
139
+ width: var(--vaadin-icon-size, 1lh);
140
+ }
141
+
142
+ [part='start-button']::before {
143
+ mask-image: var(--_vaadin-icon-play);
144
+ }
145
+
146
+ [part='retry-button']::before {
147
+ mask-image: var(--_vaadin-icon-refresh);
148
+ }
149
+
150
+ [part='remove-button']::before {
151
+ mask-image: var(--_vaadin-icon-cross);
152
+ }
153
+
154
+ ::slotted([slot='progress']) {
155
+ grid-column: 2 / -1;
156
+ width: auto;
157
+ }
158
+
159
+ :host([complete]) ::slotted([slot='progress']),
160
+ :host([error]) ::slotted([slot='progress']) {
161
+ display: none;
162
+ }
163
+
164
+ /* THUMBNAILS VARIANT */
165
+
166
+ :host([theme~='thumbnails']) {
167
+ grid-template-columns: max-content 1fr max-content;
168
+ align-items: center;
169
+ background: var(--vaadin-background-container);
170
+ padding: 0;
171
+ contain: content;
172
+
173
+ & [part] {
174
+ grid-row: 1;
175
+ }
176
+
177
+ & [part='thumbnail'],
178
+ & [part$='icon'] {
179
+ grid-column: 1;
180
+ align-self: stretch;
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
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%;
199
+ }
200
+
201
+ & [part='loader']:not([hidden]) {
202
+ place-self: center;
203
+ display: flex;
204
+ }
205
+
206
+ & [part='done-icon']::before {
207
+ background: var(--vaadin-upload-file-done-color, currentColor);
208
+ mask-image: var(--_vaadin-icon-file);
209
+ }
210
+
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'] {
226
+ clip-path: inset(50%);
227
+ width: 1px;
228
+ height: 1px;
229
+ margin: 0;
230
+ overflow: hidden;
231
+ position: absolute;
232
+ white-space: nowrap;
233
+ }
234
+
235
+ & [part='error'] {
236
+ font-size: 0.875em;
237
+ line-height: 1.25;
238
+ }
239
+
240
+ & ::slotted([slot='progress']) {
241
+ grid-row: auto;
242
+ grid-column: auto;
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;
251
+ }
252
+
253
+ & ::slotted([slot='progress'][indeterminate]) {
254
+ opacity: 0;
255
+ }
256
+ }
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
+
263
+ /* TODO: queued state styles (no attribute makes this difficult to target) */
264
+
265
+ @media (forced-colors: active) {
266
+ :is([part$='icon'], [part$='button'])::before {
267
+ background: CanvasText;
268
+ }
178
269
  }
179
- }
180
- `;
270
+ `,
271
+ ];
@@ -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: {
@@ -43,7 +43,7 @@ export interface UploadFileEventMap extends HTMLElementEventMap, UploadFileCusto
43
43
  * Part name | Description
44
44
  * -----------------|-------------
45
45
  * `thumbnail` | Image thumbnail for image files (used with `thumbnails` theme)
46
- * `file-icon` | Generic file icon for non-image files (used with `thumbnails` theme)
46
+ * `loader` | Loading spinner (used with `thumbnails` theme)
47
47
  * `done-icon` | File done status icon
48
48
  * `warning-icon` | File warning status icon
49
49
  * `meta` | Container for file name, status and error messages
@@ -23,7 +23,7 @@ import { UploadFileMixin } from './vaadin-upload-file-mixin.js';
23
23
  * Part name | Description
24
24
  * -----------------|-------------
25
25
  * `thumbnail` | Image thumbnail for image files (used with `thumbnails` theme)
26
- * `file-icon` | Generic file icon for non-image files (used with `thumbnails` theme)
26
+ * `loader` | Loading spinner (used with `thumbnails` theme)
27
27
  * `done-icon` | File done status icon
28
28
  * `warning-icon` | File warning status icon
29
29
  * `meta` | Container for file name, status and error messages
@@ -101,8 +101,13 @@ class UploadFile extends UploadFileMixin(ThemableMixin(PolylitMixin(LumoInjectio
101
101
  const isFileRetryVisible = this.errorMessage;
102
102
 
103
103
  return html`
104
- <img src="${this.__thumbnail}" alt="${this.fileName}" part="thumbnail" ?hidden="${!this.__thumbnail}" />
105
- <div part="file-icon" ?hidden="${!!this.__thumbnail}" aria-hidden="true"></div>
104
+ <div part="loader" ?hidden="${!this.uploading}" aria-hidden="true"></div>
105
+
106
+ ${this.__thumbnail
107
+ ? html`<div part="thumbnail">
108
+ <img src="${this.__thumbnail}" alt="${this.fileName}" />
109
+ </div>`
110
+ : nothing}
106
111
 
107
112
  <div part="done-icon" ?hidden="${!this.complete}" aria-hidden="true"></div>
108
113
  <div part="warning-icon" ?hidden="${!this.errorMessage}" aria-hidden="true"></div>
@@ -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,
@@ -173,7 +170,6 @@ export const UploadMixin = (superClass) =>
173
170
  /**
174
171
  * Max time in milliseconds for the entire upload process, if exceeded the
175
172
  * request will be aborted. Zero means that there is no timeout.
176
- * @type {number}
177
173
  */
178
174
  timeout: {
179
175
  type: Number,
@@ -221,7 +217,6 @@ export const UploadMixin = (superClass) =>
221
217
  * Limit of files to upload, by default it is unlimited. If the value is
222
218
  * set to one, native file browser will prevent selecting multiple files.
223
219
  * @attr {number} max-files
224
- * @type {number}
225
220
  */
226
221
  maxFiles: {
227
222
  type: Number,
@@ -232,7 +227,6 @@ export const UploadMixin = (superClass) =>
232
227
  /**
233
228
  * Specifies if the maximum number of files have been uploaded
234
229
  * @attr {boolean} max-files-reached
235
- * @type {boolean}
236
230
  */
237
231
  maxFilesReached: {
238
232
  type: Boolean,
@@ -249,7 +243,6 @@ export const UploadMixin = (superClass) =>
249
243
  * Notice that MIME types are widely supported, while file extensions
250
244
  * are only implemented in certain browsers, so avoid using it.
251
245
  * Example: accept="video/*,image/tiff" or accept=".pdf,audio/mp3"
252
- * @type {string}
253
246
  */
254
247
  accept: {
255
248
  type: String,
@@ -262,7 +255,6 @@ export const UploadMixin = (superClass) =>
262
255
  * sending the request. Obviously you need to do the same validation in
263
256
  * the server-side and be sure that they are aligned.
264
257
  * @attr {number} max-file-size
265
- * @type {number}
266
258
  */
267
259
  maxFileSize: {
268
260
  type: Number,
@@ -284,7 +276,6 @@ export const UploadMixin = (superClass) =>
284
276
  * Specifies the 'name' property at Content-Disposition for multipart uploads.
285
277
  * This property is ignored when uploadFormat is 'raw'.
286
278
  * @attr {string} form-data-name
287
- * @type {string}
288
279
  */
289
280
  formDataName: {
290
281
  type: String,
@@ -295,7 +286,6 @@ export const UploadMixin = (superClass) =>
295
286
  * Prevents upload(s) from immediately uploading upon adding file(s).
296
287
  * When set, you must manually trigger uploads using the `uploadFiles` method
297
288
  * @attr {boolean} no-auto
298
- * @type {boolean}
299
289
  */
300
290
  noAuto: {
301
291
  type: Boolean,
@@ -305,7 +295,6 @@ export const UploadMixin = (superClass) =>
305
295
  /**
306
296
  * Set the withCredentials flag on the request.
307
297
  * @attr {boolean} with-credentials
308
- * @type {boolean}
309
298
  */
310
299
  withCredentials: {
311
300
  type: Boolean,
@@ -317,7 +306,6 @@ export const UploadMixin = (superClass) =>
317
306
  * - 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default)
318
307
  * - 'multipart': Send file using multipart/form-data encoding
319
308
  * @attr {string} upload-format
320
- * @type {string}
321
309
  */
322
310
  uploadFormat: {
323
311
  type: String,
@@ -330,7 +318,6 @@ export const UploadMixin = (superClass) =>
330
318
  * uploading large numbers of files. Files exceeding this limit will be queued
331
319
  * and uploaded as active uploads complete.
332
320
  * @attr {number} max-concurrent-uploads
333
- * @type {number}
334
321
  */
335
322
  maxConcurrentUploads: {
336
323
  type: Number,
@@ -443,7 +430,7 @@ export const UploadMixin = (superClass) =>
443
430
  * }
444
431
  * }
445
432
  * ```
446
- * @return {!UploadI18n}
433
+ * @type {!UploadI18n}
447
434
  */
448
435
  get i18n() {
449
436
  return super.i18n;