@vaadin/upload 25.1.0-alpha6 → 25.1.0-alpha7

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.1.0-alpha6",
3
+ "version": "25.1.0-alpha7",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,6 +23,7 @@
23
23
  "src",
24
24
  "vaadin-*.d.ts",
25
25
  "vaadin-*.js",
26
+ "custom-elements.json",
26
27
  "web-types.json",
27
28
  "web-types.lit.json"
28
29
  ],
@@ -34,24 +35,25 @@
34
35
  ],
35
36
  "dependencies": {
36
37
  "@open-wc/dedupe-mixin": "^1.3.0",
37
- "@vaadin/a11y-base": "25.1.0-alpha6",
38
- "@vaadin/button": "25.1.0-alpha6",
39
- "@vaadin/component-base": "25.1.0-alpha6",
40
- "@vaadin/progress-bar": "25.1.0-alpha6",
41
- "@vaadin/vaadin-themable-mixin": "25.1.0-alpha6",
38
+ "@vaadin/a11y-base": "25.1.0-alpha7",
39
+ "@vaadin/button": "25.1.0-alpha7",
40
+ "@vaadin/component-base": "25.1.0-alpha7",
41
+ "@vaadin/progress-bar": "25.1.0-alpha7",
42
+ "@vaadin/vaadin-themable-mixin": "25.1.0-alpha7",
42
43
  "lit": "^3.0.0"
43
44
  },
44
45
  "devDependencies": {
45
- "@vaadin/aura": "25.1.0-alpha6",
46
- "@vaadin/chai-plugins": "25.1.0-alpha6",
47
- "@vaadin/test-runner-commands": "25.1.0-alpha6",
46
+ "@vaadin/aura": "25.1.0-alpha7",
47
+ "@vaadin/chai-plugins": "25.1.0-alpha7",
48
+ "@vaadin/test-runner-commands": "25.1.0-alpha7",
48
49
  "@vaadin/testing-helpers": "^2.0.0",
49
- "@vaadin/vaadin-lumo-styles": "25.1.0-alpha6",
50
+ "@vaadin/vaadin-lumo-styles": "25.1.0-alpha7",
50
51
  "sinon": "^21.0.0"
51
52
  },
53
+ "customElements": "custom-elements.json",
52
54
  "web-types": [
53
55
  "web-types.json",
54
56
  "web-types.lit.json"
55
57
  ],
56
- "gitHead": "da6f4194492cbd77d18c6c1cd8d4d9f072e9ce8d"
58
+ "gitHead": "98c586125f769c8fefd307536965293668fda81d"
57
59
  }
@@ -70,7 +70,7 @@ import { UploadManager } from './vaadin-upload-manager.js';
70
70
  *
71
71
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
72
72
  *
73
- * @customElement
73
+ * @customElement vaadin-upload-button
74
74
  * @extends HTMLElement
75
75
  * @mixes ButtonMixin
76
76
  * @mixes ElementMixin
@@ -128,7 +128,7 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
128
128
 
129
129
  /**
130
130
  * Whether the button is disabled.
131
- * Returns true if either explicitly disabled or maxFilesReached is true.
131
+ * Returns true if either explicitly disabled, manager is disabled, or maxFilesReached is true.
132
132
  * @type {boolean}
133
133
  * @override
134
134
  */
@@ -138,8 +138,7 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
138
138
 
139
139
  set disabled(value) {
140
140
  this.__explicitDisabled = Boolean(value);
141
- // Set super.disabled to effective value - this triggers Lit's property system correctly
142
- super.disabled = this.__explicitDisabled || this.maxFilesReached;
141
+ super.disabled = this.__effectiveDisabled;
143
142
  }
144
143
 
145
144
  /** @protected */
@@ -182,6 +181,7 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
182
181
  // Clean up manager listener to prevent memory leaks
183
182
  if (this.manager instanceof UploadManager) {
184
183
  this.manager.removeEventListener('max-files-reached-changed', this.__syncFromManager);
184
+ this.manager.removeEventListener('disabled-changed', this.__syncFromManager);
185
185
  }
186
186
  }
187
187
 
@@ -192,8 +192,9 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
192
192
  // Re-attach manager listener when reconnected to DOM
193
193
  if (this.manager instanceof UploadManager) {
194
194
  this.manager.addEventListener('max-files-reached-changed', this.__syncFromManager);
195
- this.__syncFromManager();
195
+ this.manager.addEventListener('disabled-changed', this.__syncFromManager);
196
196
  }
197
+ this.__syncFromManager();
197
198
  }
198
199
 
199
200
  /**
@@ -250,11 +251,13 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
250
251
  // Remove listener from old manager
251
252
  if (oldManager instanceof UploadManager) {
252
253
  oldManager.removeEventListener('max-files-reached-changed', this.__syncFromManager);
254
+ oldManager.removeEventListener('disabled-changed', this.__syncFromManager);
253
255
  }
254
256
 
255
257
  // Add listener to new manager and sync state only when connected
256
258
  if (this.isConnected && manager instanceof UploadManager) {
257
259
  manager.addEventListener('max-files-reached-changed', this.__syncFromManager);
260
+ manager.addEventListener('disabled-changed', this.__syncFromManager);
258
261
  this.__syncFromManager();
259
262
  } else if (this.isConnected) {
260
263
  // No manager - reset state
@@ -262,6 +265,13 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
262
265
  }
263
266
  }
264
267
 
268
+ /** @private */
269
+ get __effectiveDisabled() {
270
+ const noManager = !(this.manager instanceof UploadManager);
271
+ const managerDisabled = !noManager && this.manager.disabled;
272
+ return this.__explicitDisabled || noManager || managerDisabled || this.maxFilesReached;
273
+ }
274
+
265
275
  /** @private */
266
276
  __syncFromManager() {
267
277
  if (this.manager instanceof UploadManager) {
@@ -270,11 +280,7 @@ class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(L
270
280
  this.maxFilesReached = false;
271
281
  }
272
282
 
273
- // Sync effective disabled state
274
- const effectiveDisabled = this.__explicitDisabled || this.maxFilesReached;
275
- if (super.disabled !== effectiveDisabled) {
276
- super.disabled = effectiveDisabled;
277
- }
283
+ super.disabled = this.__effectiveDisabled;
278
284
  }
279
285
 
280
286
  /** @override */
@@ -36,7 +36,7 @@ import type { UploadManager } from './vaadin-upload-manager.js';
36
36
  * Attribute | Description
37
37
  * -------------------|--------------------------------------------
38
38
  * `dragover` | Set when files are being dragged over the element
39
- * `disabled` | Set when the drop zone is explicitly disabled
39
+ * `disabled` | Set when the drop zone is effectively disabled
40
40
  * `max-files-reached`| Set when the manager has reached maxFiles
41
41
  *
42
42
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
@@ -50,6 +50,7 @@ declare class UploadDropZone extends HTMLElement {
50
50
 
51
51
  /**
52
52
  * Whether the drop zone is disabled.
53
+ * Returns true if either explicitly disabled, manager is disabled, or no manager is set.
53
54
  */
54
55
  disabled: boolean;
55
56
 
@@ -42,12 +42,12 @@ import { UploadManager } from './vaadin-upload-manager.js';
42
42
  * Attribute | Description
43
43
  * -------------------|--------------------------------------------
44
44
  * `dragover` | Set when files are being dragged over the element
45
- * `disabled` | Set when the drop zone is explicitly disabled
45
+ * `disabled` | Set when the drop zone is effectively disabled
46
46
  * `max-files-reached`| Set when the manager has reached maxFiles
47
47
  *
48
48
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
49
49
  *
50
- * @customElement
50
+ * @customElement vaadin-upload-drop-zone
51
51
  * @extends HTMLElement
52
52
  * @mixes ElementMixin
53
53
  * @mixes ThemableMixin
@@ -80,12 +80,12 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
80
80
 
81
81
  /**
82
82
  * Whether the drop zone is disabled.
83
+ * Returns true if either explicitly disabled, manager is disabled, or no manager is set.
83
84
  * @type {boolean}
84
85
  */
85
86
  disabled: {
86
87
  type: Boolean,
87
88
  value: false,
88
- reflect: true,
89
89
  },
90
90
 
91
91
  /**
@@ -110,9 +110,27 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
110
110
  };
111
111
  }
112
112
 
113
+ /**
114
+ * Whether the drop zone is disabled.
115
+ * Returns true if either explicitly disabled, manager is disabled, or no manager is set.
116
+ * @type {boolean}
117
+ * @override
118
+ */
119
+ get disabled() {
120
+ return this.__effectiveDisabled;
121
+ }
122
+
123
+ set disabled(value) {
124
+ if (this.__syncingDisabled) return;
125
+ this.__explicitDisabled = Boolean(value);
126
+ this.__syncDisabledState();
127
+ }
128
+
113
129
  constructor() {
114
130
  super();
131
+ this.__explicitDisabled = false;
115
132
  this.__onMaxFilesReachedChanged = this.__onMaxFilesReachedChanged.bind(this);
133
+ this.__syncDisabledState = this.__syncDisabledState.bind(this);
116
134
  }
117
135
 
118
136
  /** @protected */
@@ -128,9 +146,10 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
128
146
  disconnectedCallback() {
129
147
  super.disconnectedCallback();
130
148
 
131
- // Clean up manager listener to prevent memory leaks
149
+ // Clean up manager listeners to prevent memory leaks
132
150
  if (this.manager instanceof UploadManager) {
133
151
  this.manager.removeEventListener('max-files-reached-changed', this.__onMaxFilesReachedChanged);
152
+ this.manager.removeEventListener('disabled-changed', this.__syncDisabledState);
134
153
  }
135
154
  }
136
155
 
@@ -138,13 +157,15 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
138
157
  connectedCallback() {
139
158
  super.connectedCallback();
140
159
 
141
- // Re-attach manager listener when reconnected to DOM
160
+ // Re-attach manager listeners when reconnected to DOM
142
161
  if (this.manager instanceof UploadManager) {
143
162
  this.manager.addEventListener('max-files-reached-changed', this.__onMaxFilesReachedChanged);
163
+ this.manager.addEventListener('disabled-changed', this.__syncDisabledState);
144
164
 
145
- // Sync maxFilesReached state with current manager state
165
+ // Sync state with current manager state
146
166
  this.maxFilesReached = !!this.manager.maxFilesReached;
147
167
  }
168
+ this.__syncDisabledState();
148
169
  }
149
170
 
150
171
  /** @protected */
@@ -152,14 +173,19 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
152
173
  return html`<slot></slot>`;
153
174
  }
154
175
 
176
+ /** @private */
177
+ get __effectiveDisabled() {
178
+ const noManager = !(this.manager instanceof UploadManager);
179
+ return this.__explicitDisabled || noManager || this.manager.disabled || this.maxFilesReached;
180
+ }
181
+
155
182
  /** @private */
156
183
  __onDragover(event) {
157
184
  event.preventDefault();
158
- const effectiveDisabled = this.disabled || this.maxFilesReached;
159
- if (!effectiveDisabled) {
185
+ if (!this.__effectiveDisabled) {
160
186
  this.__dragover = true;
161
187
  }
162
- event.dataTransfer.dropEffect = effectiveDisabled ? 'none' : 'copy';
188
+ event.dataTransfer.dropEffect = this.__effectiveDisabled ? 'none' : 'copy';
163
189
  }
164
190
 
165
191
  /** @private */
@@ -178,9 +204,7 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
178
204
  event.preventDefault();
179
205
  this.__dragover = false;
180
206
 
181
- // If we have a manager and not disabled, add the files
182
- const effectiveDisabled = this.disabled || this.maxFilesReached;
183
- if (!effectiveDisabled && this.manager instanceof UploadManager) {
207
+ if (!this.__effectiveDisabled) {
184
208
  const files = await getFilesFromDropEvent(event);
185
209
  this.manager.addFiles(files);
186
210
  }
@@ -188,25 +212,40 @@ class UploadDropZone extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjecti
188
212
 
189
213
  /** @private */
190
214
  __managerChanged(manager, oldManager) {
191
- // Remove listener from old manager
215
+ // Remove listeners from old manager
192
216
  if (oldManager instanceof UploadManager) {
193
217
  oldManager.removeEventListener('max-files-reached-changed', this.__onMaxFilesReachedChanged);
218
+ oldManager.removeEventListener('disabled-changed', this.__syncDisabledState);
194
219
  }
195
220
 
196
- // Add listener to new manager
221
+ // Add listeners to new manager
197
222
  if (this.isConnected && manager instanceof UploadManager) {
198
223
  manager.addEventListener('max-files-reached-changed', this.__onMaxFilesReachedChanged);
224
+ manager.addEventListener('disabled-changed', this.__syncDisabledState);
199
225
 
200
- // Sync initial state if manager has maxFilesReached property
226
+ // Sync initial state
201
227
  this.maxFilesReached = !!manager.maxFilesReached;
202
228
  } else {
203
229
  this.maxFilesReached = false;
204
230
  }
231
+
232
+ if (this.isConnected) {
233
+ this.__syncDisabledState();
234
+ }
205
235
  }
206
236
 
207
237
  /** @private */
208
238
  __onMaxFilesReachedChanged(event) {
209
239
  this.maxFilesReached = event.detail.value;
240
+ this.__syncDisabledState();
241
+ }
242
+
243
+ /** @private */
244
+ __syncDisabledState() {
245
+ if (!this.isConnected) return;
246
+ this.__syncingDisabled = true;
247
+ this.toggleAttribute('disabled', this.__effectiveDisabled);
248
+ this.__syncingDisabled = false;
210
249
  }
211
250
  }
212
251
 
@@ -88,6 +88,7 @@ export const UploadFileListMixin = (superClass) =>
88
88
  constructor() {
89
89
  super();
90
90
  this.__onManagerFilesChanged = this.__onManagerFilesChanged.bind(this);
91
+ this.__onManagerDisabledChanged = this.__onManagerDisabledChanged.bind(this);
91
92
  this.__onFileRetry = this.__onFileRetry.bind(this);
92
93
  this.__onFileAbort = this.__onFileAbort.bind(this);
93
94
  this.__onFileStart = this.__onFileStart.bind(this);
@@ -112,6 +113,7 @@ export const UploadFileListMixin = (superClass) =>
112
113
  // Clean up manager listener to prevent memory leaks
113
114
  if (this.manager instanceof UploadManager) {
114
115
  this.manager.removeEventListener('files-changed', this.__onManagerFilesChanged);
116
+ this.manager.removeEventListener('disabled-changed', this.__onManagerDisabledChanged);
115
117
  }
116
118
  }
117
119
 
@@ -122,8 +124,9 @@ export const UploadFileListMixin = (superClass) =>
122
124
  // Re-attach manager listener when reconnected to DOM
123
125
  if (this.manager instanceof UploadManager) {
124
126
  this.manager.addEventListener('files-changed', this.__onManagerFilesChanged);
127
+ this.manager.addEventListener('disabled-changed', this.__onManagerDisabledChanged);
125
128
 
126
- // Sync state with current manager files
129
+ // Sync state with current manager
127
130
  this.__syncFromManager();
128
131
  }
129
132
  }
@@ -133,11 +136,13 @@ export const UploadFileListMixin = (superClass) =>
133
136
  // Remove listeners from old manager
134
137
  if (oldManager instanceof UploadManager) {
135
138
  oldManager.removeEventListener('files-changed', this.__onManagerFilesChanged);
139
+ oldManager.removeEventListener('disabled-changed', this.__onManagerDisabledChanged);
136
140
  }
137
141
 
138
142
  // Add listeners to new manager only when connected
139
143
  if (this.isConnected && manager instanceof UploadManager) {
140
144
  manager.addEventListener('files-changed', this.__onManagerFilesChanged);
145
+ manager.addEventListener('disabled-changed', this.__onManagerDisabledChanged);
141
146
 
142
147
  // Sync initial state
143
148
  this.__syncFromManager();
@@ -152,6 +157,11 @@ export const UploadFileListMixin = (superClass) =>
152
157
  this.__syncFromManager();
153
158
  }
154
159
 
160
+ /** @private */
161
+ __onManagerDisabledChanged() {
162
+ this.requestContentUpdate();
163
+ }
164
+
155
165
  /** @private */
156
166
  __syncFromManager() {
157
167
  if (this.manager instanceof UploadManager) {
@@ -322,6 +332,8 @@ export const UploadFileListMixin = (superClass) =>
322
332
  /** @private */
323
333
  requestContentUpdate() {
324
334
  const { items, __effectiveI18n: i18n, disabled } = this;
335
+ const managerDisabled = this.manager instanceof UploadManager && this.manager.disabled;
336
+ const effectiveDisabled = disabled || managerDisabled;
325
337
 
326
338
  render(
327
339
  html`
@@ -329,7 +341,7 @@ export const UploadFileListMixin = (superClass) =>
329
341
  (file) => html`
330
342
  <li>
331
343
  <vaadin-upload-file
332
- .disabled="${disabled}"
344
+ .disabled="${effectiveDisabled}"
333
345
  .file="${file}"
334
346
  .complete="${file.complete}"
335
347
  .errorMessage="${file.error}"
@@ -340,7 +352,11 @@ export const UploadFileListMixin = (superClass) =>
340
352
  .status="${file.status}"
341
353
  .uploading="${file.uploading}"
342
354
  .i18n="${i18n}"
343
- theme="${ifDefined(this._theme)}"
355
+ theme="${ifDefined(
356
+ window.Vaadin.featureFlags.modularUpload || window.Vaadin.featureFlags.aiComponents
357
+ ? this._theme
358
+ : undefined,
359
+ )}"
344
360
  ></vaadin-upload-file>
345
361
  </li>
346
362
  `,
@@ -75,7 +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
- * @customElement
78
+ * @customElement vaadin-upload-file-list
79
79
  * @extends HTMLElement
80
80
  * @mixes ThemableMixin
81
81
  * @mixes UploadFileListMixin
@@ -77,7 +77,7 @@ 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
- * @customElement
80
+ * @customElement vaadin-upload-file
81
81
  * @extends HTMLElement
82
82
  * @mixes UploadFileMixin
83
83
  * @mixes ThemableMixin
@@ -12,7 +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
- * @customElement
15
+ * @customElement vaadin-upload-icon
16
16
  * @extends HTMLElement
17
17
  * @private
18
18
  */
@@ -125,6 +125,13 @@ export interface UploadManagerOptions {
125
125
  * @default 'file'
126
126
  */
127
127
  formDataName?: string;
128
+
129
+ /**
130
+ * Whether the upload manager is disabled.
131
+ * When true, connected components (upload-button, upload-drop-zone) will be automatically disabled.
132
+ * @default false
133
+ */
134
+ disabled?: boolean;
128
135
  }
129
136
 
130
137
  export interface UploadManagerEventMap {
@@ -147,6 +154,7 @@ export interface UploadManagerEventMap {
147
154
  'upload-abort': CustomEvent<{ file: UploadFile; xhr: XMLHttpRequest }>;
148
155
  'files-changed': CustomEvent<{ value: UploadFile[] }>;
149
156
  'max-files-reached-changed': CustomEvent<{ value: boolean }>;
157
+ 'disabled-changed': CustomEvent<{ value: boolean }>;
150
158
  }
151
159
 
152
160
  /**
@@ -292,6 +300,12 @@ export class UploadManager extends EventTarget {
292
300
  */
293
301
  readonly maxFilesReached: boolean;
294
302
 
303
+ /**
304
+ * Whether the upload manager is disabled.
305
+ * When true, connected components (upload-button, upload-drop-zone) will be automatically disabled.
306
+ */
307
+ disabled: boolean;
308
+
295
309
  /**
296
310
  * Add files to the upload list.
297
311
  */
@@ -4,11 +4,19 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
7
+ window.Vaadin = window.Vaadin || {};
8
+ window.Vaadin.featureFlags = window.Vaadin.featureFlags || {};
9
+
7
10
  /**
8
11
  * A pure JavaScript class that manages file upload state and XHR requests.
9
12
  * It has no knowledge of UI components - components should listen to events and
10
13
  * call methods to interact with the manager.
11
14
  *
15
+ * **Note:** This class is experimental and requires the `modularUpload` or `aiComponents` feature flag to be enabled:
16
+ * ```javascript
17
+ * window.Vaadin.featureFlags.modularUpload = true;
18
+ * ```
19
+ *
12
20
  * @example
13
21
  * ```javascript
14
22
  * import { UploadManager } from '@vaadin/upload';
@@ -50,6 +58,7 @@
50
58
  * @fires {CustomEvent} upload-abort - Fired when abort is requested
51
59
  * @fires {CustomEvent} files-changed - Fired when the files array changes
52
60
  * @fires {CustomEvent} max-files-reached-changed - Fired when maxFilesReached changes
61
+ * @fires {CustomEvent} disabled-changed - Fired when disabled changes
53
62
  */
54
63
  export class UploadManager extends EventTarget {
55
64
  /** @type {Array<UploadFile>} */
@@ -58,6 +67,9 @@ export class UploadManager extends EventTarget {
58
67
  /** @type {boolean} */
59
68
  #maxFilesReached = false;
60
69
 
70
+ /** @type {boolean} */
71
+ #disabled = false;
72
+
61
73
  /** @type {Array<UploadFile>} */
62
74
  #uploadQueue = [];
63
75
 
@@ -91,10 +103,17 @@ export class UploadManager extends EventTarget {
91
103
  * @param {string} [options.uploadFormat='raw'] - Specifies the upload format to use when sending files to the server. 'raw': Send file as raw binary data with the file's MIME type as Content-Type (default). 'multipart': Send file using multipart/form-data encoding.
92
104
  * @param {number} [options.maxConcurrentUploads=3] - Specifies the maximum number of files that can be uploaded simultaneously. This helps prevent browser performance degradation and XHR limitations when uploading large numbers of files. Files exceeding this limit will be queued and uploaded as active uploads complete.
93
105
  * @param {string} [options.formDataName='file'] - Specifies the 'name' property at Content-Disposition for multipart uploads. This property is ignored when uploadFormat is 'raw'.
106
+ * @param {boolean} [options.disabled=false] - Whether the upload manager is disabled. When true, connected components (upload-button, upload-drop-zone) will be automatically disabled.
94
107
  */
95
108
  constructor(options = {}) {
96
109
  super();
97
110
 
111
+ if (!window.Vaadin.featureFlags.modularUpload && !window.Vaadin.featureFlags.aiComponents) {
112
+ throw new Error(
113
+ 'UploadManager requires the modularUpload feature flag. Enable it with: window.Vaadin.featureFlags.modularUpload = true',
114
+ );
115
+ }
116
+
98
117
  // Configuration properties - use setters for validation
99
118
  this.target = options.target || '';
100
119
  this.method = options.method || 'POST';
@@ -108,6 +127,7 @@ export class UploadManager extends EventTarget {
108
127
  this.uploadFormat = options.uploadFormat || 'raw';
109
128
  this.maxConcurrentUploads = options.maxConcurrentUploads === undefined ? 3 : options.maxConcurrentUploads;
110
129
  this.formDataName = options.formDataName || 'file';
130
+ this.disabled = options.disabled === undefined ? false : options.disabled;
111
131
  }
112
132
 
113
133
  /**
@@ -241,6 +261,27 @@ export class UploadManager extends EventTarget {
241
261
  return this.#maxFilesReached;
242
262
  }
243
263
 
264
+ /**
265
+ * Whether the upload manager is disabled.
266
+ * When true, connected components (upload-button, upload-drop-zone) will be automatically disabled.
267
+ * @type {boolean}
268
+ */
269
+ get disabled() {
270
+ return this.#disabled;
271
+ }
272
+
273
+ set disabled(value) {
274
+ const disabled = Boolean(value);
275
+ if (disabled !== this.#disabled) {
276
+ this.#disabled = disabled;
277
+ this.dispatchEvent(
278
+ new CustomEvent('disabled-changed', {
279
+ detail: { value: disabled },
280
+ }),
281
+ );
282
+ }
283
+ }
284
+
244
285
  /**
245
286
  * Add files to the upload list.
246
287
  * @param {FileList|File[]} files - Files to add
@@ -590,7 +590,12 @@ export const UploadMixin = (superClass) =>
590
590
  list.items = [...files];
591
591
  list.i18n = effectiveI18n;
592
592
  list.disabled = disabled;
593
- if (this._theme) {
593
+ if (
594
+ window.Vaadin &&
595
+ window.Vaadin.featureFlags &&
596
+ (window.Vaadin.featureFlags.modularUpload || window.Vaadin.featureFlags.aiComponents) &&
597
+ this._theme
598
+ ) {
594
599
  list.setAttribute('theme', this._theme);
595
600
  } else {
596
601
  list.removeAttribute('theme');
@@ -101,7 +101,7 @@ import { UploadMixin } from './vaadin-upload-mixin.js';
101
101
  * @fires {CustomEvent} upload-retry - Fired when retry upload is requested.
102
102
  * @fires {CustomEvent} upload-abort - Fired when upload abort is requested.
103
103
  *
104
- * @customElement
104
+ * @customElement vaadin-upload
105
105
  * @extends HTMLElement
106
106
  * @mixes ThemableMixin
107
107
  * @mixes ElementMixin
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.1.0-alpha6",
4
+ "version": "25.1.0-alpha7",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -55,7 +55,7 @@
55
55
  "properties": [
56
56
  {
57
57
  "name": "disabled",
58
- "description": "Whether the button is disabled.\nReturns true if either explicitly disabled or maxFilesReached is true.",
58
+ "description": "Whether the button is disabled.\nReturns true if either explicitly disabled, manager is disabled, or maxFilesReached is true.",
59
59
  "value": {
60
60
  "type": [
61
61
  "?"
@@ -96,11 +96,11 @@
96
96
  },
97
97
  {
98
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.",
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 effectively 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
100
  "attributes": [
101
101
  {
102
102
  "name": "disabled",
103
- "description": "Whether the drop zone is disabled.",
103
+ "description": "Whether the drop zone is disabled.\nReturns true if either explicitly disabled, manager is disabled, or no manager is set.",
104
104
  "value": {
105
105
  "type": [
106
106
  "boolean"
@@ -131,21 +131,21 @@
131
131
  "js": {
132
132
  "properties": [
133
133
  {
134
- "name": "manager",
135
- "description": "Reference to an UploadManager.\nWhen set, dropped files will be automatically added to the manager.",
134
+ "name": "disabled",
135
+ "description": "Whether the drop zone is disabled.\nReturns true if either explicitly disabled, manager is disabled, or no manager is set.",
136
136
  "value": {
137
137
  "type": [
138
- "Object",
139
- "null"
138
+ "boolean"
140
139
  ]
141
140
  }
142
141
  },
143
142
  {
144
- "name": "disabled",
145
- "description": "Whether the drop zone is disabled.",
143
+ "name": "manager",
144
+ "description": "Reference to an UploadManager.\nWhen set, dropped files will be automatically added to the manager.",
146
145
  "value": {
147
146
  "type": [
148
- "boolean"
147
+ "Object",
148
+ "null"
149
149
  ]
150
150
  }
151
151
  },