@vaadin/upload 25.0.3 → 25.1.0-alpha2
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/README.md +23 -0
- package/package.json +11 -11
- package/src/styles/vaadin-upload-button-base-styles.d.ts +8 -0
- package/src/styles/vaadin-upload-button-base-styles.js +11 -0
- package/src/styles/vaadin-upload-drop-zone-base-styles.d.ts +8 -0
- package/src/styles/vaadin-upload-drop-zone-base-styles.js +26 -0
- package/src/vaadin-upload-button.d.ts +100 -0
- package/src/vaadin-upload-button.js +288 -0
- package/src/vaadin-upload-drop-zone.d.ts +72 -0
- package/src/vaadin-upload-drop-zone.js +215 -0
- package/src/vaadin-upload-file-list-mixin.d.ts +74 -0
- package/src/vaadin-upload-file-list-mixin.js +281 -15
- package/src/vaadin-upload-file-list.d.ts +83 -0
- package/src/vaadin-upload-file-list.js +62 -2
- package/src/vaadin-upload-file.js +5 -2
- package/src/vaadin-upload-helpers.js +48 -0
- package/src/vaadin-upload-manager.d.ts +345 -0
- package/src/vaadin-upload-manager.js +720 -0
- package/src/vaadin-upload-mixin.d.ts +10 -0
- package/src/vaadin-upload-mixin.js +79 -57
- package/vaadin-upload-button.d.ts +1 -0
- package/vaadin-upload-button.js +3 -0
- package/vaadin-upload-drop-zone.d.ts +1 -0
- package/vaadin-upload-drop-zone.js +3 -0
- package/vaadin-upload-file-list.d.ts +1 -0
- package/vaadin-upload-file-list.js +3 -0
- package/vaadin-upload-manager.d.ts +1 -0
- package/vaadin-upload-manager.js +1 -0
- package/web-types.json +258 -1
- package/web-types.lit.json +106 -1
package/README.md
CHANGED
|
@@ -28,6 +28,29 @@ Once installed, import the component in your application:
|
|
|
28
28
|
import '@vaadin/upload';
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
## Performance Considerations
|
|
32
|
+
|
|
33
|
+
When uploading large numbers of files, the component automatically throttles concurrent uploads to prevent browser performance degradation. By default, a maximum of 3 files are uploaded simultaneously, with additional files queued automatically.
|
|
34
|
+
|
|
35
|
+
You can customize this limit using the `max-concurrent-uploads` attribute:
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<!-- Limit to 5 concurrent uploads -->
|
|
39
|
+
<vaadin-upload max-concurrent-uploads="5"></vaadin-upload>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
// Or set it programmatically
|
|
44
|
+
upload.maxConcurrentUploads = 5;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This helps prevent:
|
|
48
|
+
- Browser XHR limitations (failures when uploading 2000+ files simultaneously)
|
|
49
|
+
- Performance degradation with hundreds of concurrent uploads
|
|
50
|
+
- Network congestion on slower connections
|
|
51
|
+
|
|
52
|
+
The default value of 3 balances upload performance with network resource conservation.
|
|
53
|
+
|
|
31
54
|
## Contributing
|
|
32
55
|
|
|
33
56
|
Read the [contributing guide](https://vaadin.com/docs/latest/contributing) to learn about our development process, how to propose bugfixes and improvements, and how to test your changes to Vaadin components.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/upload",
|
|
3
|
-
"version": "25.0
|
|
3
|
+
"version": "25.1.0-alpha2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -34,24 +34,24 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
37
|
-
"@vaadin/a11y-base": "
|
|
38
|
-
"@vaadin/button": "
|
|
39
|
-
"@vaadin/component-base": "
|
|
40
|
-
"@vaadin/progress-bar": "
|
|
41
|
-
"@vaadin/vaadin-themable-mixin": "
|
|
37
|
+
"@vaadin/a11y-base": "25.1.0-alpha2",
|
|
38
|
+
"@vaadin/button": "25.1.0-alpha2",
|
|
39
|
+
"@vaadin/component-base": "25.1.0-alpha2",
|
|
40
|
+
"@vaadin/progress-bar": "25.1.0-alpha2",
|
|
41
|
+
"@vaadin/vaadin-themable-mixin": "25.1.0-alpha2",
|
|
42
42
|
"lit": "^3.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@vaadin/aura": "
|
|
46
|
-
"@vaadin/chai-plugins": "
|
|
47
|
-
"@vaadin/test-runner-commands": "
|
|
45
|
+
"@vaadin/aura": "25.1.0-alpha2",
|
|
46
|
+
"@vaadin/chai-plugins": "25.1.0-alpha2",
|
|
47
|
+
"@vaadin/test-runner-commands": "25.1.0-alpha2",
|
|
48
48
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
49
|
-
"@vaadin/vaadin-lumo-styles": "
|
|
49
|
+
"@vaadin/vaadin-lumo-styles": "25.1.0-alpha2",
|
|
50
50
|
"sinon": "^21.0.0"
|
|
51
51
|
},
|
|
52
52
|
"web-types": [
|
|
53
53
|
"web-types.json",
|
|
54
54
|
"web-types.lit.json"
|
|
55
55
|
],
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "dfeb6e14643ec923e5505ca645f7354c6dc170ec"
|
|
57
57
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { CSSResult } from 'lit';
|
|
7
|
+
|
|
8
|
+
export declare const uploadButtonStyles: CSSResult[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css } from 'lit';
|
|
7
|
+
import { buttonStyles } from '@vaadin/button/src/styles/vaadin-button-base-styles.js';
|
|
8
|
+
|
|
9
|
+
const uploadButton = css``;
|
|
10
|
+
|
|
11
|
+
export const uploadButtonStyles = [buttonStyles, uploadButton];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { CSSResult } from 'lit';
|
|
7
|
+
|
|
8
|
+
export declare const uploadDropZoneStyles: CSSResult;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import '@vaadin/component-base/src/styles/style-props.js';
|
|
7
|
+
import { css } from 'lit';
|
|
8
|
+
|
|
9
|
+
export const uploadDropZoneStyles = css`
|
|
10
|
+
:host {
|
|
11
|
+
display: block;
|
|
12
|
+
position: relative;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
:host([dragover])::after {
|
|
16
|
+
content: '';
|
|
17
|
+
position: absolute;
|
|
18
|
+
inset: 0;
|
|
19
|
+
background: var(--vaadin-background-container);
|
|
20
|
+
opacity: 0.7;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:host([hidden]) {
|
|
24
|
+
display: none !important;
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { ButtonMixin } from '@vaadin/button/src/vaadin-button-mixin.js';
|
|
7
|
+
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
8
|
+
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
9
|
+
import type { UploadManager } from './vaadin-upload-manager.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `<vaadin-upload-button>` is a button component for file uploads.
|
|
13
|
+
* When clicked, it opens a file picker dialog and calls addFiles
|
|
14
|
+
* on a linked UploadManager.
|
|
15
|
+
*
|
|
16
|
+
* ```html
|
|
17
|
+
* <vaadin-upload-button>Upload Files</vaadin-upload-button>
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* The button must be linked to an UploadManager by setting the
|
|
21
|
+
* `manager` property:
|
|
22
|
+
*
|
|
23
|
+
* ```javascript
|
|
24
|
+
* const button = document.querySelector('vaadin-upload-button');
|
|
25
|
+
* button.manager = uploadManager;
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* ### Styling
|
|
29
|
+
*
|
|
30
|
+
* The following shadow DOM parts are available for styling:
|
|
31
|
+
*
|
|
32
|
+
* Part name | Description
|
|
33
|
+
* ----------|-------------
|
|
34
|
+
* `label` | The label (text) inside the button.
|
|
35
|
+
* `prefix` | A slot for content before the label (e.g. an icon).
|
|
36
|
+
* `suffix` | A slot for content after the label (e.g. an icon).
|
|
37
|
+
*
|
|
38
|
+
* The following state attributes are available for styling:
|
|
39
|
+
*
|
|
40
|
+
* Attribute | Description
|
|
41
|
+
* -------------------|-------------
|
|
42
|
+
* `active` | Set when the button is pressed down, either with mouse, touch or the keyboard
|
|
43
|
+
* `disabled` | Set when the button is disabled
|
|
44
|
+
* `focus-ring` | Set when the button is focused using the keyboard
|
|
45
|
+
* `focused` | Set when the button is focused
|
|
46
|
+
* `has-tooltip` | Set when the button has a slotted tooltip
|
|
47
|
+
* `max-files-reached`| Set when the manager has reached maxFiles
|
|
48
|
+
*
|
|
49
|
+
* The following custom CSS properties are available for styling:
|
|
50
|
+
*
|
|
51
|
+
* Custom CSS property |
|
|
52
|
+
* :----------------------------------|
|
|
53
|
+
* | `--vaadin-button-background` |
|
|
54
|
+
* | `--vaadin-button-border-color` |
|
|
55
|
+
* | `--vaadin-button-border-radius` |
|
|
56
|
+
* | `--vaadin-button-border-width` |
|
|
57
|
+
* | `--vaadin-button-font-size` |
|
|
58
|
+
* | `--vaadin-button-font-weight` |
|
|
59
|
+
* | `--vaadin-button-gap` |
|
|
60
|
+
* | `--vaadin-button-height` |
|
|
61
|
+
* | `--vaadin-button-line-height` |
|
|
62
|
+
* | `--vaadin-button-margin` |
|
|
63
|
+
* | `--vaadin-button-padding` |
|
|
64
|
+
* | `--vaadin-button-text-color` |
|
|
65
|
+
*
|
|
66
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
67
|
+
*/
|
|
68
|
+
declare class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(HTMLElement))) {
|
|
69
|
+
/**
|
|
70
|
+
* Reference to an UploadManager.
|
|
71
|
+
* When set, the button will automatically disable when maxFilesReached
|
|
72
|
+
* becomes true on the manager. The file picker will also use the manager's
|
|
73
|
+
* `accept` and `maxFiles` settings.
|
|
74
|
+
*/
|
|
75
|
+
manager: UploadManager | null;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Capture attribute for mobile file input.
|
|
79
|
+
*/
|
|
80
|
+
capture: string | undefined;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* True when max files has been reached on the manager.
|
|
84
|
+
* The button will not open the file picker when this is true.
|
|
85
|
+
*/
|
|
86
|
+
maxFilesReached: boolean;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Opens the file picker dialog.
|
|
90
|
+
*/
|
|
91
|
+
openFilePicker(): void;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
declare global {
|
|
95
|
+
interface HTMLElementTagNameMap {
|
|
96
|
+
'vaadin-upload-button': UploadButton;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { UploadButton };
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { html, LitElement } from 'lit';
|
|
7
|
+
import { ButtonMixin } from '@vaadin/button/src/vaadin-button-mixin.js';
|
|
8
|
+
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
9
|
+
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
10
|
+
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
11
|
+
import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
|
|
12
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
13
|
+
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
14
|
+
import { uploadButtonStyles } from './styles/vaadin-upload-button-base-styles.js';
|
|
15
|
+
import { UploadManager } from './vaadin-upload-manager.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `<vaadin-upload-button>` is a button component for file uploads.
|
|
19
|
+
* When clicked, it opens a file picker dialog and calls addFiles
|
|
20
|
+
* on a linked UploadManager.
|
|
21
|
+
*
|
|
22
|
+
* ```html
|
|
23
|
+
* <vaadin-upload-button>Upload Files</vaadin-upload-button>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* The button must be linked to an UploadManager by setting the
|
|
27
|
+
* `manager` property:
|
|
28
|
+
*
|
|
29
|
+
* ```javascript
|
|
30
|
+
* const button = document.querySelector('vaadin-upload-button');
|
|
31
|
+
* button.manager = uploadManager;
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* ### Styling
|
|
35
|
+
*
|
|
36
|
+
* The following shadow DOM parts are available for styling:
|
|
37
|
+
*
|
|
38
|
+
* Part name | Description
|
|
39
|
+
* ----------|-------------
|
|
40
|
+
* `label` | The label (text) inside the button.
|
|
41
|
+
* `prefix` | A slot for content before the label (e.g. an icon).
|
|
42
|
+
* `suffix` | A slot for content after the label (e.g. an icon).
|
|
43
|
+
*
|
|
44
|
+
* The following state attributes are available for styling:
|
|
45
|
+
*
|
|
46
|
+
* Attribute | Description
|
|
47
|
+
* ---------------|-------------
|
|
48
|
+
* `active` | Set when the button is pressed down, either with mouse, touch or the keyboard
|
|
49
|
+
* `disabled` | Set when the button is disabled
|
|
50
|
+
* `focus-ring` | Set when the button is focused using the keyboard
|
|
51
|
+
* `focused` | Set when the button is focused
|
|
52
|
+
* `has-tooltip` | Set when the button has a slotted tooltip
|
|
53
|
+
*
|
|
54
|
+
* The following custom CSS properties are available for styling:
|
|
55
|
+
*
|
|
56
|
+
* Custom CSS property |
|
|
57
|
+
* :----------------------------------|
|
|
58
|
+
* | `--vaadin-button-background` |
|
|
59
|
+
* | `--vaadin-button-border-color` |
|
|
60
|
+
* | `--vaadin-button-border-radius` |
|
|
61
|
+
* | `--vaadin-button-border-width` |
|
|
62
|
+
* | `--vaadin-button-font-size` |
|
|
63
|
+
* | `--vaadin-button-font-weight` |
|
|
64
|
+
* | `--vaadin-button-gap` |
|
|
65
|
+
* | `--vaadin-button-height` |
|
|
66
|
+
* | `--vaadin-button-line-height` |
|
|
67
|
+
* | `--vaadin-button-margin` |
|
|
68
|
+
* | `--vaadin-button-padding` |
|
|
69
|
+
* | `--vaadin-button-text-color` |
|
|
70
|
+
*
|
|
71
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
72
|
+
*
|
|
73
|
+
* @customElement
|
|
74
|
+
* @extends HTMLElement
|
|
75
|
+
* @mixes ButtonMixin
|
|
76
|
+
* @mixes ElementMixin
|
|
77
|
+
* @mixes ThemableMixin
|
|
78
|
+
*/
|
|
79
|
+
class UploadButton extends ButtonMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
80
|
+
static get is() {
|
|
81
|
+
return 'vaadin-upload-button';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static get styles() {
|
|
85
|
+
return uploadButtonStyles;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static get properties() {
|
|
89
|
+
return {
|
|
90
|
+
/**
|
|
91
|
+
* Reference to an UploadManager.
|
|
92
|
+
* When set, the button will automatically disable when maxFilesReached
|
|
93
|
+
* becomes true on the manager.
|
|
94
|
+
* @type {Object | null}
|
|
95
|
+
*/
|
|
96
|
+
manager: {
|
|
97
|
+
type: Object,
|
|
98
|
+
value: null,
|
|
99
|
+
observer: '__managerChanged',
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Capture attribute for mobile file input.
|
|
104
|
+
* @type {string}
|
|
105
|
+
*/
|
|
106
|
+
capture: {
|
|
107
|
+
type: String,
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* True when max files has been reached on the manager.
|
|
112
|
+
* @type {boolean}
|
|
113
|
+
*/
|
|
114
|
+
maxFilesReached: {
|
|
115
|
+
type: Boolean,
|
|
116
|
+
value: false,
|
|
117
|
+
reflect: true,
|
|
118
|
+
attribute: 'max-files-reached',
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
constructor() {
|
|
124
|
+
super();
|
|
125
|
+
this.__syncFromManager = this.__syncFromManager.bind(this);
|
|
126
|
+
this.__explicitDisabled = false;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Whether the button is disabled.
|
|
131
|
+
* Returns true if either explicitly disabled or maxFilesReached is true.
|
|
132
|
+
* @type {boolean}
|
|
133
|
+
* @override
|
|
134
|
+
*/
|
|
135
|
+
get disabled() {
|
|
136
|
+
return super.disabled;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
set disabled(value) {
|
|
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;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** @protected */
|
|
146
|
+
render() {
|
|
147
|
+
return html`
|
|
148
|
+
<div class="vaadin-button-container">
|
|
149
|
+
<span part="prefix" aria-hidden="true">
|
|
150
|
+
<slot name="prefix"></slot>
|
|
151
|
+
</span>
|
|
152
|
+
<span part="label">
|
|
153
|
+
<slot></slot>
|
|
154
|
+
</span>
|
|
155
|
+
<span part="suffix" aria-hidden="true">
|
|
156
|
+
<slot name="suffix"></slot>
|
|
157
|
+
</span>
|
|
158
|
+
</div>
|
|
159
|
+
<slot name="tooltip"></slot>
|
|
160
|
+
<input id="fileInput" type="file" hidden @change=${this.__onFileInputChange} />
|
|
161
|
+
`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** @protected */
|
|
165
|
+
ready() {
|
|
166
|
+
super.ready();
|
|
167
|
+
|
|
168
|
+
// Add tooltip support
|
|
169
|
+
this._tooltipController = new TooltipController(this);
|
|
170
|
+
this.addController(this._tooltipController);
|
|
171
|
+
|
|
172
|
+
// Open file picker on click
|
|
173
|
+
this.addEventListener('click', () => {
|
|
174
|
+
this.openFilePicker();
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** @protected */
|
|
179
|
+
disconnectedCallback() {
|
|
180
|
+
super.disconnectedCallback();
|
|
181
|
+
|
|
182
|
+
// Clean up manager listener to prevent memory leaks
|
|
183
|
+
if (this.manager instanceof UploadManager) {
|
|
184
|
+
this.manager.removeEventListener('max-files-reached-changed', this.__syncFromManager);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** @protected */
|
|
189
|
+
connectedCallback() {
|
|
190
|
+
super.connectedCallback();
|
|
191
|
+
|
|
192
|
+
// Re-attach manager listener when reconnected to DOM
|
|
193
|
+
if (this.manager instanceof UploadManager) {
|
|
194
|
+
this.manager.addEventListener('max-files-reached-changed', this.__syncFromManager);
|
|
195
|
+
this.__syncFromManager();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Opens the file picker dialog.
|
|
201
|
+
*/
|
|
202
|
+
openFilePicker() {
|
|
203
|
+
if (this.disabled) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Update file input attributes before opening
|
|
208
|
+
this.__updateFileInputAttributes();
|
|
209
|
+
|
|
210
|
+
this.$.fileInput.value = '';
|
|
211
|
+
this.$.fileInput.click();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** @private */
|
|
215
|
+
__updateFileInputAttributes() {
|
|
216
|
+
const { fileInput } = this.$;
|
|
217
|
+
|
|
218
|
+
// Set accept attribute from manager
|
|
219
|
+
const accept = this.manager && this.manager.accept;
|
|
220
|
+
if (accept) {
|
|
221
|
+
fileInput.setAttribute('accept', accept);
|
|
222
|
+
} else {
|
|
223
|
+
fileInput.removeAttribute('accept');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Set multiple attribute based on manager's maxFiles
|
|
227
|
+
const maxFiles = this.manager && this.manager.maxFiles != null ? this.manager.maxFiles : Infinity;
|
|
228
|
+
fileInput.multiple = maxFiles !== 1;
|
|
229
|
+
|
|
230
|
+
// Set capture attribute
|
|
231
|
+
if (this.capture) {
|
|
232
|
+
fileInput.setAttribute('capture', this.capture);
|
|
233
|
+
} else {
|
|
234
|
+
fileInput.removeAttribute('capture');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** @private */
|
|
239
|
+
__onFileInputChange(event) {
|
|
240
|
+
const files = event.target.files;
|
|
241
|
+
|
|
242
|
+
// If we have a manager, call addFiles
|
|
243
|
+
if (this.manager instanceof UploadManager) {
|
|
244
|
+
this.manager.addFiles(files);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** @private */
|
|
249
|
+
__managerChanged(manager, oldManager) {
|
|
250
|
+
// Remove listener from old manager
|
|
251
|
+
if (oldManager instanceof UploadManager) {
|
|
252
|
+
oldManager.removeEventListener('max-files-reached-changed', this.__syncFromManager);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Add listener to new manager and sync state only when connected
|
|
256
|
+
if (this.isConnected && manager instanceof UploadManager) {
|
|
257
|
+
manager.addEventListener('max-files-reached-changed', this.__syncFromManager);
|
|
258
|
+
this.__syncFromManager();
|
|
259
|
+
} else if (this.isConnected) {
|
|
260
|
+
// No manager - reset state
|
|
261
|
+
this.__syncFromManager();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** @private */
|
|
266
|
+
__syncFromManager() {
|
|
267
|
+
if (this.manager instanceof UploadManager) {
|
|
268
|
+
this.maxFilesReached = this.manager.maxFilesReached;
|
|
269
|
+
} else {
|
|
270
|
+
this.maxFilesReached = false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Sync effective disabled state
|
|
274
|
+
const effectiveDisabled = this.__explicitDisabled || this.maxFilesReached;
|
|
275
|
+
if (super.disabled !== effectiveDisabled) {
|
|
276
|
+
super.disabled = effectiveDisabled;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** @override */
|
|
281
|
+
__shouldAllowFocusWhenDisabled() {
|
|
282
|
+
return window.Vaadin.featureFlags.accessibleDisabledButtons;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
defineCustomElement(UploadButton);
|
|
287
|
+
|
|
288
|
+
export { UploadButton };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2000 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
|
|
7
|
+
import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
8
|
+
import type { UploadManager } from './vaadin-upload-manager.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `<vaadin-upload-drop-zone>` is a Web Component that can be used as a drop zone
|
|
12
|
+
* for file uploads. When files are dropped on the drop zone, they are added to
|
|
13
|
+
* a linked UploadManager.
|
|
14
|
+
*
|
|
15
|
+
* ```html
|
|
16
|
+
* <vaadin-upload-drop-zone>
|
|
17
|
+
* <p>Drop files here</p>
|
|
18
|
+
* </vaadin-upload-drop-zone>
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* The drop zone must be linked to an UploadManager by setting the
|
|
22
|
+
* `manager` property:
|
|
23
|
+
*
|
|
24
|
+
* ```javascript
|
|
25
|
+
* const dropZone = document.querySelector('vaadin-upload-drop-zone');
|
|
26
|
+
* dropZone.manager = uploadManager;
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* ### Styling
|
|
30
|
+
*
|
|
31
|
+
* The component has no styling by default. When files are dragged over,
|
|
32
|
+
* the `dragover` attribute is set and the component uses a hover effect.
|
|
33
|
+
* To override the hover effect, use `vaadin-upload-drop-zone[dragover]::after`
|
|
34
|
+
* selector to style the pseudo-element covering the drop zone during dragover.
|
|
35
|
+
*
|
|
36
|
+
* Attribute | Description
|
|
37
|
+
* -------------------|--------------------------------------------
|
|
38
|
+
* `dragover` | Set when files are being dragged over the element
|
|
39
|
+
* `disabled` | Set when the drop zone is explicitly disabled
|
|
40
|
+
* `max-files-reached`| Set when the manager has reached maxFiles
|
|
41
|
+
*
|
|
42
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
43
|
+
*/
|
|
44
|
+
declare class UploadDropZone extends HTMLElement {
|
|
45
|
+
/**
|
|
46
|
+
* Reference to an UploadManager.
|
|
47
|
+
* When set, dropped files will be automatically added to the manager.
|
|
48
|
+
*/
|
|
49
|
+
manager: UploadManager | null;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether the drop zone is disabled.
|
|
53
|
+
*/
|
|
54
|
+
disabled: boolean;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* True when max files has been reached on the manager.
|
|
58
|
+
* The drop zone will not accept files when this is true.
|
|
59
|
+
* @readonly
|
|
60
|
+
*/
|
|
61
|
+
readonly maxFilesReached: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface UploadDropZone extends ElementMixinClass, ThemableMixinClass {}
|
|
65
|
+
|
|
66
|
+
declare global {
|
|
67
|
+
interface HTMLElementTagNameMap {
|
|
68
|
+
'vaadin-upload-drop-zone': UploadDropZone;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { UploadDropZone };
|