@exmg/exm-upload 1.1.36 → 1.2.0
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/.rollup.cache/root/repo/packages/exm-upload/dist/exm-dialog-upload-base.d.ts +90 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-dialog-upload-base.js +226 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-dialog-upload.d.ts +11 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-dialog-upload.js +15 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-base.d.ts +148 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-base.js +373 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-crop-base.d.ts +16 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-crop-base.js +76 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-crop.d.ts +9 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-crop.js +12 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-drop-area-base.d.ts +8 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-drop-area-base.js +34 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-drop-area.d.ts +9 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-drop-area.js +12 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-input.d.ts +15 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-input.js +84 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-item-base.d.ts +45 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-item-base.js +175 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-item.d.ts +9 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload-item.js +12 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload.d.ts +19 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/exm-upload.js +22 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/index.d.ts +19 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/index.js +18 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/mixins/exm-upload-drag-drop-mixin.d.ts +10 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/mixins/exm-upload-drag-drop-mixin.js +28 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-dialog-upload-css.d.ts +1 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-dialog-upload-css.js +253 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-crop-styles-css.d.ts +1 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-crop-styles-css.js +324 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-drop-area-styles-css.d.ts +1 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-drop-area-styles-css.js +52 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-input-css.d.ts +1 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-input-css.js +22 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-item-styles-css.d.ts +1 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-item-styles-css.js +124 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-styles-css.d.ts +1 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/styles/exm-upload-styles-css.js +150 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/types.d.ts +33 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/types.js +10 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/upload/adapters/form-data-adapter.d.ts +7 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/upload/adapters/local-adapter.d.ts +6 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/upload/adapters/xhr-adapter.d.ts +9 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/upload/index.d.ts +1 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/upload/service.d.ts +9 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/upload/service.js +45 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/upload/types.d.ts +12 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/utils.d.ts +33 -0
- package/.rollup.cache/root/repo/packages/exm-upload/dist/utils.js +89 -0
- package/dist/exm-dialog-upload-base.js +6 -4
- package/dist/exm-dialog-upload.js +4 -2
- package/dist/exm-upload-base.js +9 -7
- package/dist/exm-upload-crop-base.js +7 -4
- package/dist/exm-upload-crop.js +4 -2
- package/dist/exm-upload-drop-area-base.js +6 -3
- package/dist/exm-upload-drop-area.js +4 -2
- package/dist/exm-upload-input.js +5 -3
- package/dist/exm-upload-item-base.js +9 -6
- package/dist/exm-upload-item.js +4 -2
- package/dist/exm-upload.js +4 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/mixins/exm-upload-drag-drop-mixin.js +6 -3
- package/dist/styles/exm-dialog-upload-css.js +5 -2
- package/dist/styles/exm-upload-crop-styles-css.js +5 -2
- package/dist/styles/exm-upload-drop-area-styles-css.js +5 -2
- package/dist/styles/exm-upload-input-css.js +5 -2
- package/dist/styles/exm-upload-item-styles-css.js +5 -2
- package/dist/styles/exm-upload-styles-css.js +5 -2
- package/dist/types.js +5 -3
- package/dist/upload/service.js +2 -1
- package/dist/utils.js +8 -10
- package/package.json +5 -5
- /package/{dist → .rollup.cache/root/repo/packages/exm-upload/dist}/upload/adapters/form-data-adapter.js +0 -0
- /package/{dist → .rollup.cache/root/repo/packages/exm-upload/dist}/upload/adapters/local-adapter.js +0 -0
- /package/{dist → .rollup.cache/root/repo/packages/exm-upload/dist}/upload/adapters/xhr-adapter.js +0 -0
- /package/{dist → .rollup.cache/root/repo/packages/exm-upload/dist}/upload/index.js +0 -0
- /package/{dist → .rollup.cache/root/repo/packages/exm-upload/dist}/upload/types.js +0 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { html } from 'lit';
|
|
3
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
4
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
5
|
+
import { repeat } from 'lit/directives/repeat.js';
|
|
6
|
+
import '@material/web/icon/icon.js';
|
|
7
|
+
import { FileUploadError } from './types.js';
|
|
8
|
+
// File upload imports
|
|
9
|
+
import './exm-upload-item.js';
|
|
10
|
+
import './exm-upload-crop.js';
|
|
11
|
+
import './exm-upload-drop-area.js';
|
|
12
|
+
import { isCorrectResolution, isImage, isSizeValid, isTypeValidExtension } from './utils.js';
|
|
13
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
14
|
+
import { ExmgElement, observer } from '@exmg/lit-base';
|
|
15
|
+
export class ExmUploadBase extends ExmgElement {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
/**
|
|
19
|
+
* Files addded to component
|
|
20
|
+
*/
|
|
21
|
+
this.files = [];
|
|
22
|
+
/**
|
|
23
|
+
* Accepted file types seperated by comma
|
|
24
|
+
*/
|
|
25
|
+
this.accept = '';
|
|
26
|
+
/**
|
|
27
|
+
* The max file size allowed to upload e.g. '20mb'
|
|
28
|
+
*/
|
|
29
|
+
this.maxSize = '100mb';
|
|
30
|
+
/**
|
|
31
|
+
* Determines if multiple files can be selected. When false maxAmount is set to 1 automatically
|
|
32
|
+
*/
|
|
33
|
+
this.multiple = false;
|
|
34
|
+
/**
|
|
35
|
+
* Disable the upload component useful for forms
|
|
36
|
+
*/
|
|
37
|
+
this.disabled = false;
|
|
38
|
+
/**
|
|
39
|
+
* The upload response type
|
|
40
|
+
*/
|
|
41
|
+
this.responseType = 'json';
|
|
42
|
+
/**
|
|
43
|
+
* The upload response type
|
|
44
|
+
*/
|
|
45
|
+
this.serverType = 'xhr';
|
|
46
|
+
/**
|
|
47
|
+
* The CropperJS config see: https://github.com/fengyuanchen/cropperjs#options
|
|
48
|
+
*/
|
|
49
|
+
this.cropperConfig = {};
|
|
50
|
+
this._cropperConfig = {
|
|
51
|
+
modal: true,
|
|
52
|
+
center: true,
|
|
53
|
+
dragMode: 'move',
|
|
54
|
+
movable: true,
|
|
55
|
+
scalable: true,
|
|
56
|
+
guides: true,
|
|
57
|
+
zoomOnWheel: true,
|
|
58
|
+
cropBoxMovable: true,
|
|
59
|
+
wheelZoomRatio: 0.1,
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Internal state to check if user is cropping or not
|
|
63
|
+
*/
|
|
64
|
+
this._isCropping = false;
|
|
65
|
+
this.isModeDialog = false;
|
|
66
|
+
/**
|
|
67
|
+
* Internal state to check if file is uploaded or not
|
|
68
|
+
*/
|
|
69
|
+
this._uploaded = false;
|
|
70
|
+
/**
|
|
71
|
+
* Allow cropping can only be used when fixedResolution is not set
|
|
72
|
+
*/
|
|
73
|
+
this.allowCropping = false;
|
|
74
|
+
}
|
|
75
|
+
getValues() {
|
|
76
|
+
return this.files.filter((file) => file.status === 'UPLOADED').map((file) => file.url);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Extract files from either file input or drop event
|
|
80
|
+
* @param event
|
|
81
|
+
* @returns FileList[] | []
|
|
82
|
+
*/
|
|
83
|
+
_getFiles(event) {
|
|
84
|
+
var _a;
|
|
85
|
+
const { files } = (_a = (event.type === 'drop' ? event.dataTransfer : event.target)) !== null && _a !== void 0 ? _a : {};
|
|
86
|
+
return Array.from(files !== null && files !== void 0 ? files : []);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resets the upload component
|
|
90
|
+
* @public
|
|
91
|
+
*/
|
|
92
|
+
reset() {
|
|
93
|
+
this._uploaded = false;
|
|
94
|
+
this.files = [];
|
|
95
|
+
this.cancelActiveCrop();
|
|
96
|
+
}
|
|
97
|
+
prepareFiles(addedFiles) {
|
|
98
|
+
// Loop through files and assign unique id
|
|
99
|
+
const newFiles = addedFiles.map((item) => ({
|
|
100
|
+
id: (Date.now() + Math.random()).toString(36),
|
|
101
|
+
file: item,
|
|
102
|
+
status: 'UPLOADING',
|
|
103
|
+
}));
|
|
104
|
+
for (const file of newFiles) {
|
|
105
|
+
this._validateFile(file);
|
|
106
|
+
this.files = [...this.files, file];
|
|
107
|
+
}
|
|
108
|
+
this.fire('files-changed', { files: this.files }, true);
|
|
109
|
+
this._uploaded = true;
|
|
110
|
+
if (this.fileElement) {
|
|
111
|
+
this.fileElement.value = '';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Handles file change which also validates
|
|
116
|
+
* @param event
|
|
117
|
+
* @fires files-changed
|
|
118
|
+
*/
|
|
119
|
+
async _handleChange(event) {
|
|
120
|
+
event.preventDefault();
|
|
121
|
+
if (this.disabled) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// clear error files
|
|
125
|
+
this.files = [...this.files.filter((item) => !item.invalid)];
|
|
126
|
+
const addedFiles = this._getFiles(event);
|
|
127
|
+
this.prepareFiles(addedFiles);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Validator function to check file before upload to server
|
|
131
|
+
* @param FileData
|
|
132
|
+
*/
|
|
133
|
+
async _validateFile(item) {
|
|
134
|
+
if (!isSizeValid(item.file.size, this.maxSize)) {
|
|
135
|
+
this._handleError(FileUploadError.INVALID_SIZE, item);
|
|
136
|
+
}
|
|
137
|
+
if (!isTypeValidExtension(item.file, this.accept || '')) {
|
|
138
|
+
this._handleError(FileUploadError.INVALID_TYPE, item);
|
|
139
|
+
}
|
|
140
|
+
if (this.maxAmount && this.files.length >= this.maxAmount) {
|
|
141
|
+
this._handleError(FileUploadError.INVALID_AMOUNT, item);
|
|
142
|
+
}
|
|
143
|
+
if (!this.multiple && this.files.length >= 1) {
|
|
144
|
+
this._handleError(FileUploadError.INVALID_MULTIPLE, item);
|
|
145
|
+
}
|
|
146
|
+
const _isImage = isImage(item.file);
|
|
147
|
+
if (_isImage && this.fixedResolution) {
|
|
148
|
+
const isCorrect = await isCorrectResolution(item.file, this.fixedResolution);
|
|
149
|
+
if (!isCorrect) {
|
|
150
|
+
this._handleError(FileUploadError.INVALID_RESOLUTION, item);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Enable cropping mode
|
|
156
|
+
* @param e
|
|
157
|
+
*/
|
|
158
|
+
_handleCropping(e) {
|
|
159
|
+
const file = e.detail;
|
|
160
|
+
this._isCropping = true;
|
|
161
|
+
setTimeout(() => { var _a; return (_a = this.cropSection) === null || _a === void 0 ? void 0 : _a.crop(file); });
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Removes file from files array
|
|
165
|
+
* @param id
|
|
166
|
+
*/
|
|
167
|
+
removeFile(id) {
|
|
168
|
+
this.files = this.files.filter((item) => {
|
|
169
|
+
return item.id !== id;
|
|
170
|
+
});
|
|
171
|
+
this.fire('file-removed', id);
|
|
172
|
+
this.fire('files-changed', { files: this.files }, true);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Removes the file out of the files array.
|
|
176
|
+
* @fires file-removed
|
|
177
|
+
* @param e
|
|
178
|
+
* @param id
|
|
179
|
+
*/
|
|
180
|
+
_handleRemove(e) {
|
|
181
|
+
const idToRemove = e.detail;
|
|
182
|
+
this.removeFile(idToRemove);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Handles crop done and toggles cropping state
|
|
186
|
+
* @fires crop-done
|
|
187
|
+
* @param e
|
|
188
|
+
*/
|
|
189
|
+
async _handleCropDone(e) {
|
|
190
|
+
this._isCropping = false;
|
|
191
|
+
const item = e.detail;
|
|
192
|
+
this.removeFile(item === null || item === void 0 ? void 0 : item.id);
|
|
193
|
+
this.prepareFiles([item.file]);
|
|
194
|
+
this.fire('crop-done', e.detail, true);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Handles crop cancel and toggles cropping state
|
|
198
|
+
* @fires crop-cancel
|
|
199
|
+
*/
|
|
200
|
+
cancelActiveCrop() {
|
|
201
|
+
this._isCropping = false;
|
|
202
|
+
this.fire('crop-cancel', {}, true);
|
|
203
|
+
}
|
|
204
|
+
saveActiveCrop() {
|
|
205
|
+
var _a;
|
|
206
|
+
(_a = this.cropSection) === null || _a === void 0 ? void 0 : _a.saveCropArea();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Error handling helper function used for all validation
|
|
210
|
+
* @param message
|
|
211
|
+
* @param item
|
|
212
|
+
*/
|
|
213
|
+
_handleError(message, item) {
|
|
214
|
+
item.invalid = true;
|
|
215
|
+
item.status = 'INVALID';
|
|
216
|
+
item.error = message;
|
|
217
|
+
}
|
|
218
|
+
openFileSelector(e) {
|
|
219
|
+
var _a;
|
|
220
|
+
e.preventDefault();
|
|
221
|
+
const fileInput = (_a = this === null || this === void 0 ? void 0 : this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#file');
|
|
222
|
+
if (fileInput) {
|
|
223
|
+
fileInput.click();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
renderDescription() {
|
|
227
|
+
const { accept, maxSize, fixedResolution } = this;
|
|
228
|
+
return `Only ${accept ? accept.replace(/,/g, ' ') : ''} files${fixedResolution ? ` of resolution ${fixedResolution} px` : ''} that do not exceed ${maxSize} in size`;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Renders the file items
|
|
232
|
+
*/
|
|
233
|
+
renderFileItems() {
|
|
234
|
+
return repeat(this.files || [], (file) => file.id, (item) => html `<exm-upload-item
|
|
235
|
+
class="item"
|
|
236
|
+
id=${item.id}
|
|
237
|
+
@edit-image=${this._handleCropping}
|
|
238
|
+
@remove-item=${this._handleRemove}
|
|
239
|
+
uploadUrl=${ifDefined(this.uploadUrl)}
|
|
240
|
+
customAdapterPath=${ifDefined(this.customAdapterPath)}
|
|
241
|
+
serverType=${this.serverType}
|
|
242
|
+
responseType=${this.responseType}
|
|
243
|
+
?allowCropping=${!this.fixedResolution && this.allowCropping}
|
|
244
|
+
.item=${item}
|
|
245
|
+
></exm-upload-item>`);
|
|
246
|
+
}
|
|
247
|
+
renderUploadCrop() {
|
|
248
|
+
const { _cropperConfig } = this;
|
|
249
|
+
return html `
|
|
250
|
+
<exm-upload-crop
|
|
251
|
+
id="crop-dialog"
|
|
252
|
+
?hideActions=${this.isModeDialog}
|
|
253
|
+
@crop-done=${this._handleCropDone}
|
|
254
|
+
@crop-cancel=${this.cancelActiveCrop}
|
|
255
|
+
.cropperConfig=${_cropperConfig}
|
|
256
|
+
></exm-upload-crop>
|
|
257
|
+
`;
|
|
258
|
+
}
|
|
259
|
+
renderUploadDropArea() {
|
|
260
|
+
const { disabled } = this;
|
|
261
|
+
return html `
|
|
262
|
+
<exm-upload-drop-area
|
|
263
|
+
description=${this.renderDescription()}
|
|
264
|
+
?disabled=${disabled}
|
|
265
|
+
@browse-files=${this.openFileSelector}
|
|
266
|
+
@remove-file=${this._handleRemove}
|
|
267
|
+
@drop=${this._handleChange}
|
|
268
|
+
>
|
|
269
|
+
<slot slot="drop-icon" name="drop-icon">
|
|
270
|
+
<md-icon>upload</md-icon>
|
|
271
|
+
</slot>
|
|
272
|
+
<slot slot="drop-text" name="drop-text"
|
|
273
|
+
>Drag and drop, or <a href="#" @click=${this.openFileSelector}>browse</a> your files</slot
|
|
274
|
+
>
|
|
275
|
+
</exm-upload-drop-area>
|
|
276
|
+
`;
|
|
277
|
+
}
|
|
278
|
+
render() {
|
|
279
|
+
const { _isCropping, accept, disabled } = this;
|
|
280
|
+
if (_isCropping) {
|
|
281
|
+
return this.renderUploadCrop();
|
|
282
|
+
}
|
|
283
|
+
return html `
|
|
284
|
+
<div class="image-upload-wrapper ${classMap({ disabled: !!this.disabled })}">
|
|
285
|
+
${this.renderUploadDropArea()}
|
|
286
|
+
|
|
287
|
+
<form id="form-upload" enctype="multipart/form-data">
|
|
288
|
+
<input
|
|
289
|
+
id="file"
|
|
290
|
+
type="file"
|
|
291
|
+
name="file"
|
|
292
|
+
tabindex="-1"
|
|
293
|
+
accept=${ifDefined(accept)}
|
|
294
|
+
?disabled=${disabled}
|
|
295
|
+
@change=${this._handleChange}
|
|
296
|
+
?multiple=${this.multiple}
|
|
297
|
+
hidden
|
|
298
|
+
/>
|
|
299
|
+
</form>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<!-- Upload Items list -->
|
|
303
|
+
<div class="item-container">${this.renderFileItems()}</div>
|
|
304
|
+
`;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
__decorate([
|
|
308
|
+
property({ type: String })
|
|
309
|
+
], ExmUploadBase.prototype, "for", void 0);
|
|
310
|
+
__decorate([
|
|
311
|
+
property({ type: Array })
|
|
312
|
+
], ExmUploadBase.prototype, "files", void 0);
|
|
313
|
+
__decorate([
|
|
314
|
+
property({ type: String })
|
|
315
|
+
], ExmUploadBase.prototype, "accept", void 0);
|
|
316
|
+
__decorate([
|
|
317
|
+
property({ type: String })
|
|
318
|
+
], ExmUploadBase.prototype, "maxSize", void 0);
|
|
319
|
+
__decorate([
|
|
320
|
+
property({ type: Boolean })
|
|
321
|
+
], ExmUploadBase.prototype, "multiple", void 0);
|
|
322
|
+
__decorate([
|
|
323
|
+
property({ type: Number })
|
|
324
|
+
], ExmUploadBase.prototype, "maxAmount", void 0);
|
|
325
|
+
__decorate([
|
|
326
|
+
property({ type: Boolean })
|
|
327
|
+
], ExmUploadBase.prototype, "disabled", void 0);
|
|
328
|
+
__decorate([
|
|
329
|
+
property({ type: String })
|
|
330
|
+
], ExmUploadBase.prototype, "customAdapterPath", void 0);
|
|
331
|
+
__decorate([
|
|
332
|
+
property({ type: String })
|
|
333
|
+
], ExmUploadBase.prototype, "uploadUrl", void 0);
|
|
334
|
+
__decorate([
|
|
335
|
+
property({ type: String })
|
|
336
|
+
], ExmUploadBase.prototype, "responseType", void 0);
|
|
337
|
+
__decorate([
|
|
338
|
+
property({ type: String })
|
|
339
|
+
], ExmUploadBase.prototype, "serverType", void 0);
|
|
340
|
+
__decorate([
|
|
341
|
+
property({ type: Object }),
|
|
342
|
+
observer(function (value) {
|
|
343
|
+
this._cropperConfig = { ...this._cropperConfig, ...value };
|
|
344
|
+
})
|
|
345
|
+
], ExmUploadBase.prototype, "cropperConfig", void 0);
|
|
346
|
+
__decorate([
|
|
347
|
+
state()
|
|
348
|
+
], ExmUploadBase.prototype, "_cropperConfig", void 0);
|
|
349
|
+
__decorate([
|
|
350
|
+
state()
|
|
351
|
+
], ExmUploadBase.prototype, "_isCropping", void 0);
|
|
352
|
+
__decorate([
|
|
353
|
+
property({ type: Boolean })
|
|
354
|
+
], ExmUploadBase.prototype, "isModeDialog", void 0);
|
|
355
|
+
__decorate([
|
|
356
|
+
state()
|
|
357
|
+
], ExmUploadBase.prototype, "_uploaded", void 0);
|
|
358
|
+
__decorate([
|
|
359
|
+
query('#crop-dialog')
|
|
360
|
+
], ExmUploadBase.prototype, "cropSection", void 0);
|
|
361
|
+
__decorate([
|
|
362
|
+
property({ type: Boolean })
|
|
363
|
+
], ExmUploadBase.prototype, "allowCropping", void 0);
|
|
364
|
+
__decorate([
|
|
365
|
+
property({ type: String })
|
|
366
|
+
], ExmUploadBase.prototype, "fixedResolution", void 0);
|
|
367
|
+
__decorate([
|
|
368
|
+
query('#file')
|
|
369
|
+
], ExmUploadBase.prototype, "fileElement", void 0);
|
|
370
|
+
__decorate([
|
|
371
|
+
query('.item-container')
|
|
372
|
+
], ExmUploadBase.prototype, "itemContainer", void 0);
|
|
373
|
+
//# sourceMappingURL=exm-upload-base.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import '@material/web/button/filled-button.js';
|
|
2
|
+
import { FileData } from './types.js';
|
|
3
|
+
import { ExmgElement } from '@exmg/lit-base';
|
|
4
|
+
export declare class ExmUploadCropBase extends ExmgElement {
|
|
5
|
+
cropperConfig: any;
|
|
6
|
+
cropArea?: HTMLImageElement;
|
|
7
|
+
hideActions: boolean;
|
|
8
|
+
_item?: FileData;
|
|
9
|
+
private cropper?;
|
|
10
|
+
protected firstUpdated(): void;
|
|
11
|
+
crop(item: FileData): Promise<void>;
|
|
12
|
+
_cancel(): void;
|
|
13
|
+
saveCropArea(): void;
|
|
14
|
+
renderActions(): import("lit-html").TemplateResult<1>;
|
|
15
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { html, nothing } from 'lit';
|
|
3
|
+
import { query, property, state } from 'lit/decorators.js';
|
|
4
|
+
import '@material/web/button/filled-button.js';
|
|
5
|
+
import { ExmgElement } from '@exmg/lit-base';
|
|
6
|
+
import Cropper from 'cropperjs';
|
|
7
|
+
export class ExmUploadCropBase extends ExmgElement {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.cropperConfig = {};
|
|
11
|
+
this.hideActions = false;
|
|
12
|
+
}
|
|
13
|
+
firstUpdated() {
|
|
14
|
+
this.fire('crop-start', {}, true);
|
|
15
|
+
}
|
|
16
|
+
async crop(item) {
|
|
17
|
+
this._item = item;
|
|
18
|
+
const reader = new FileReader();
|
|
19
|
+
reader.onload = () => {
|
|
20
|
+
if (this.cropArea) {
|
|
21
|
+
this.cropArea.src = reader.result;
|
|
22
|
+
}
|
|
23
|
+
this.cropper = new Cropper(this.cropArea, this.cropperConfig);
|
|
24
|
+
};
|
|
25
|
+
if (item.file) {
|
|
26
|
+
reader.readAsDataURL(item.file);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
_cancel() {
|
|
30
|
+
this.fire('crop-cancel', {}, true);
|
|
31
|
+
}
|
|
32
|
+
saveCropArea() {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
const canvas = (_a = this.cropper) === null || _a === void 0 ? void 0 : _a.getCroppedCanvas();
|
|
35
|
+
if (!canvas) {
|
|
36
|
+
throw new Error('Cropper canvas not found');
|
|
37
|
+
}
|
|
38
|
+
canvas === null || canvas === void 0 ? void 0 : canvas.toBlob((blob) => {
|
|
39
|
+
if (!this._item || !blob) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const file = new File([blob], `cropped-${this._item.file.name}`, { type: this._item.file.type });
|
|
43
|
+
this._item.file = file;
|
|
44
|
+
this.fire('crop-done', this._item);
|
|
45
|
+
}, (_b = this._item) === null || _b === void 0 ? void 0 : _b.file.type);
|
|
46
|
+
}
|
|
47
|
+
renderActions() {
|
|
48
|
+
return html `
|
|
49
|
+
<div class="actions">
|
|
50
|
+
<md-filled-button @click=${this._cancel}>Cancel</md-filled-button>
|
|
51
|
+
<md-filled-button @click=${this.saveCropArea}>Crop</md-filled-button>
|
|
52
|
+
</div>
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
render() {
|
|
56
|
+
return html `
|
|
57
|
+
<div class="image-container">
|
|
58
|
+
<img id="image" />
|
|
59
|
+
</div>
|
|
60
|
+
${this.hideActions ? nothing : this.renderActions()}
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
__decorate([
|
|
65
|
+
property({ type: Object })
|
|
66
|
+
], ExmUploadCropBase.prototype, "cropperConfig", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
query('#image')
|
|
69
|
+
], ExmUploadCropBase.prototype, "cropArea", void 0);
|
|
70
|
+
__decorate([
|
|
71
|
+
property({ type: Boolean })
|
|
72
|
+
], ExmUploadCropBase.prototype, "hideActions", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
state()
|
|
75
|
+
], ExmUploadCropBase.prototype, "_item", void 0);
|
|
76
|
+
//# sourceMappingURL=exm-upload-crop-base.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ExmUploadCropBase } from './exm-upload-crop-base.js';
|
|
2
|
+
export declare class ExmUploadCrop extends ExmUploadCropBase {
|
|
3
|
+
static styles: import("lit").CSSResult;
|
|
4
|
+
}
|
|
5
|
+
declare global {
|
|
6
|
+
interface HTMLElementTagNameMap {
|
|
7
|
+
'exm-upload-crop': ExmUploadCrop;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
import { style } from './styles/exm-upload-crop-styles-css.js';
|
|
4
|
+
import { ExmUploadCropBase } from './exm-upload-crop-base.js';
|
|
5
|
+
let ExmUploadCrop = class ExmUploadCrop extends ExmUploadCropBase {
|
|
6
|
+
};
|
|
7
|
+
ExmUploadCrop.styles = style;
|
|
8
|
+
ExmUploadCrop = __decorate([
|
|
9
|
+
customElement('exm-upload-crop')
|
|
10
|
+
], ExmUploadCrop);
|
|
11
|
+
export { ExmUploadCrop };
|
|
12
|
+
//# sourceMappingURL=exm-upload-crop.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ExmgElement } from '@exmg/lit-base';
|
|
2
|
+
declare const ExmUploadDropAreaBase_base: (new (...args: any[]) => import("./mixins/exm-upload-drag-drop-mixin.js").DragAndDropInterface) & typeof ExmgElement;
|
|
3
|
+
export declare class ExmUploadDropAreaBase extends ExmUploadDropAreaBase_base {
|
|
4
|
+
description?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
7
|
+
}
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { html } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators.js';
|
|
4
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
5
|
+
import { DragAndDropMixin } from './mixins/exm-upload-drag-drop-mixin.js';
|
|
6
|
+
import { ExmgElement } from '@exmg/lit-base';
|
|
7
|
+
export class ExmUploadDropAreaBase extends DragAndDropMixin(ExmgElement) {
|
|
8
|
+
render() {
|
|
9
|
+
return html ` <div
|
|
10
|
+
class="drop ${classMap({
|
|
11
|
+
disabled: !!this.disabled,
|
|
12
|
+
dropHover: this.dragOver && !this.disabled,
|
|
13
|
+
})}"
|
|
14
|
+
@dragover=${this.onDragOver}
|
|
15
|
+
@dragleave=${this.onDragLeave}
|
|
16
|
+
@drop=${this.onDrop}
|
|
17
|
+
>
|
|
18
|
+
<div class="drop-container">
|
|
19
|
+
<slot name="drop-icon"></slot>
|
|
20
|
+
<span class="drop-text">
|
|
21
|
+
<slot name="drop-text"></slot>
|
|
22
|
+
</span>
|
|
23
|
+
<span class="description">${this.description}</span>
|
|
24
|
+
</div>
|
|
25
|
+
</div>`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
__decorate([
|
|
29
|
+
property({ type: String })
|
|
30
|
+
], ExmUploadDropAreaBase.prototype, "description", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
property({ type: Boolean })
|
|
33
|
+
], ExmUploadDropAreaBase.prototype, "disabled", void 0);
|
|
34
|
+
//# sourceMappingURL=exm-upload-drop-area-base.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ExmUploadDropAreaBase } from './exm-upload-drop-area-base.js';
|
|
2
|
+
export declare class ExmUploadDropArea extends ExmUploadDropAreaBase {
|
|
3
|
+
static styles: import("lit").CSSResult;
|
|
4
|
+
}
|
|
5
|
+
declare global {
|
|
6
|
+
interface HTMLElementTagNameMap {
|
|
7
|
+
'exm-upload-drop-area': ExmUploadDropArea;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
import { style } from './styles/exm-upload-drop-area-styles-css.js';
|
|
4
|
+
import { ExmUploadDropAreaBase } from './exm-upload-drop-area-base.js';
|
|
5
|
+
let ExmUploadDropArea = class ExmUploadDropArea extends ExmUploadDropAreaBase {
|
|
6
|
+
};
|
|
7
|
+
ExmUploadDropArea.styles = style;
|
|
8
|
+
ExmUploadDropArea = __decorate([
|
|
9
|
+
customElement('exm-upload-drop-area')
|
|
10
|
+
], ExmUploadDropArea);
|
|
11
|
+
export { ExmUploadDropArea };
|
|
12
|
+
//# sourceMappingURL=exm-upload-drop-area.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import '@exmg/exm-collapsed';
|
|
3
|
+
import { ExmUpload } from './exm-upload.js';
|
|
4
|
+
export declare class ExmUploadInput extends LitElement {
|
|
5
|
+
opened: boolean;
|
|
6
|
+
closeDelay: number;
|
|
7
|
+
static styles: import("lit").CSSResult[];
|
|
8
|
+
getUploadElement(): ExmUpload;
|
|
9
|
+
getInputElement(): HTMLInputElement;
|
|
10
|
+
protected firstUpdated(): void;
|
|
11
|
+
toggle(): void;
|
|
12
|
+
_uploadSuccess(): void;
|
|
13
|
+
handleClick(e: CustomEvent): void;
|
|
14
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { LitElement, html } from 'lit';
|
|
3
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
+
import '@exmg/exm-collapsed';
|
|
5
|
+
import { style } from './styles/exm-upload-input-css.js';
|
|
6
|
+
let ExmUploadInput = class ExmUploadInput extends LitElement {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.opened = false;
|
|
10
|
+
this.closeDelay = 400;
|
|
11
|
+
}
|
|
12
|
+
getUploadElement() {
|
|
13
|
+
return this.querySelector('exm-upload');
|
|
14
|
+
}
|
|
15
|
+
getInputElement() {
|
|
16
|
+
return this.querySelector('[slot="input"]');
|
|
17
|
+
}
|
|
18
|
+
firstUpdated() {
|
|
19
|
+
const upload = this.getUploadElement();
|
|
20
|
+
if (upload) {
|
|
21
|
+
if (upload.multiple) {
|
|
22
|
+
console.warn('exm-upload-input: multiple is not supported, forcing to false');
|
|
23
|
+
upload.multiple = false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
toggle() {
|
|
28
|
+
this.opened = !this.opened;
|
|
29
|
+
}
|
|
30
|
+
_uploadSuccess() {
|
|
31
|
+
const upload = this.getUploadElement();
|
|
32
|
+
const input = this.getInputElement();
|
|
33
|
+
if (!input || !upload) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const response = upload.getValues()[0];
|
|
37
|
+
let value = '';
|
|
38
|
+
try {
|
|
39
|
+
const d = JSON.parse(response);
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
value = d.url ? d.url : response;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
value = response;
|
|
45
|
+
}
|
|
46
|
+
input.value = value;
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
upload.reset();
|
|
49
|
+
this.opened = false;
|
|
50
|
+
}, this.closeDelay);
|
|
51
|
+
}
|
|
52
|
+
handleClick(e) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
const el = e.target;
|
|
55
|
+
const slotValue = el.getAttribute('slot');
|
|
56
|
+
if (el.tagName.toLowerCase() === 'md-icon-button' && slotValue === 'trailing-icon') {
|
|
57
|
+
this.toggle();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
render() {
|
|
61
|
+
return html `
|
|
62
|
+
<div class="input-wrapper">
|
|
63
|
+
<div class="input" aria-expanded=${this.opened} aria-controls="collapsed">
|
|
64
|
+
<slot name="input" @click=${this.handleClick}></slot>
|
|
65
|
+
</div>
|
|
66
|
+
<exm-collapsed id="collapsed" ?opened=${this.opened}>
|
|
67
|
+
<slot name="upload" @upload-success=${this._uploadSuccess}></slot>
|
|
68
|
+
</exm-collapsed>
|
|
69
|
+
</div>
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
ExmUploadInput.styles = [style];
|
|
74
|
+
__decorate([
|
|
75
|
+
property({ type: Boolean })
|
|
76
|
+
], ExmUploadInput.prototype, "opened", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
property({ type: Number })
|
|
79
|
+
], ExmUploadInput.prototype, "closeDelay", void 0);
|
|
80
|
+
ExmUploadInput = __decorate([
|
|
81
|
+
customElement('exm-upload-input')
|
|
82
|
+
], ExmUploadInput);
|
|
83
|
+
export { ExmUploadInput };
|
|
84
|
+
//# sourceMappingURL=exm-upload-input.js.map
|