@exmg/exm-upload 1.0.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.
Files changed (60) hide show
  1. package/README.md +20 -0
  2. package/index.d.ts +18 -0
  3. package/index.js +17 -0
  4. package/package.json +53 -0
  5. package/src/exm-dialog-upload-base.d.ts +90 -0
  6. package/src/exm-dialog-upload-base.js +226 -0
  7. package/src/exm-dialog-upload.d.ts +11 -0
  8. package/src/exm-dialog-upload.js +15 -0
  9. package/src/exm-upload-base.d.ts +148 -0
  10. package/src/exm-upload-base.js +373 -0
  11. package/src/exm-upload-crop-base.d.ts +16 -0
  12. package/src/exm-upload-crop-base.js +76 -0
  13. package/src/exm-upload-crop.d.ts +9 -0
  14. package/src/exm-upload-crop.js +12 -0
  15. package/src/exm-upload-drop-area-base.d.ts +8 -0
  16. package/src/exm-upload-drop-area-base.js +34 -0
  17. package/src/exm-upload-drop-area.d.ts +9 -0
  18. package/src/exm-upload-drop-area.js +12 -0
  19. package/src/exm-upload-input.d.ts +15 -0
  20. package/src/exm-upload-input.js +84 -0
  21. package/src/exm-upload-item-base.d.ts +45 -0
  22. package/src/exm-upload-item-base.js +177 -0
  23. package/src/exm-upload-item.d.ts +9 -0
  24. package/src/exm-upload-item.js +12 -0
  25. package/src/exm-upload.d.ts +19 -0
  26. package/src/exm-upload.js +22 -0
  27. package/src/mixins/exm-upload-drag-drop-mixin.d.ts +10 -0
  28. package/src/mixins/exm-upload-drag-drop-mixin.js +28 -0
  29. package/src/styles/exm-dialog-upload-css.d.ts +2 -0
  30. package/src/styles/exm-dialog-upload-css.js +4 -0
  31. package/src/styles/exm-dialog-upload.scss +22 -0
  32. package/src/styles/exm-upload-crop-styles-css.d.ts +2 -0
  33. package/src/styles/exm-upload-crop-styles-css.js +12 -0
  34. package/src/styles/exm-upload-crop-styles.scss +323 -0
  35. package/src/styles/exm-upload-drop-area-styles-css.d.ts +2 -0
  36. package/src/styles/exm-upload-drop-area-styles-css.js +4 -0
  37. package/src/styles/exm-upload-drop-area-styles.scss +45 -0
  38. package/src/styles/exm-upload-input-css.d.ts +2 -0
  39. package/src/styles/exm-upload-input-css.js +4 -0
  40. package/src/styles/exm-upload-input.scss +18 -0
  41. package/src/styles/exm-upload-item-styles-css.d.ts +2 -0
  42. package/src/styles/exm-upload-item-styles-css.js +4 -0
  43. package/src/styles/exm-upload-item-styles.scss +119 -0
  44. package/src/styles/exm-upload-styles-css.d.ts +2 -0
  45. package/src/styles/exm-upload-styles-css.js +4 -0
  46. package/src/styles/exm-upload-styles.scss +147 -0
  47. package/src/types.d.ts +33 -0
  48. package/src/types.js +10 -0
  49. package/src/upload/adapters/local-adapter.d.ts +6 -0
  50. package/src/upload/adapters/local-adapter.js +23 -0
  51. package/src/upload/adapters/xhr-adapter.d.ts +9 -0
  52. package/src/upload/adapters/xhr-adapter.js +49 -0
  53. package/src/upload/index.d.ts +1 -0
  54. package/src/upload/index.js +2 -0
  55. package/src/upload/service.d.ts +9 -0
  56. package/src/upload/service.js +42 -0
  57. package/src/upload/types.d.ts +12 -0
  58. package/src/upload/types.js +2 -0
  59. package/src/utils.d.ts +33 -0
  60. package/src/utils.js +89 -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 ExmgUploadBase 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
+ ], ExmgUploadBase.prototype, "for", void 0);
310
+ __decorate([
311
+ property({ type: Array })
312
+ ], ExmgUploadBase.prototype, "files", void 0);
313
+ __decorate([
314
+ property({ type: String })
315
+ ], ExmgUploadBase.prototype, "accept", void 0);
316
+ __decorate([
317
+ property({ type: String })
318
+ ], ExmgUploadBase.prototype, "maxSize", void 0);
319
+ __decorate([
320
+ property({ type: Boolean })
321
+ ], ExmgUploadBase.prototype, "multiple", void 0);
322
+ __decorate([
323
+ property({ type: Number })
324
+ ], ExmgUploadBase.prototype, "maxAmount", void 0);
325
+ __decorate([
326
+ property({ type: Boolean })
327
+ ], ExmgUploadBase.prototype, "disabled", void 0);
328
+ __decorate([
329
+ property({ type: String })
330
+ ], ExmgUploadBase.prototype, "customAdapterPath", void 0);
331
+ __decorate([
332
+ property({ type: String })
333
+ ], ExmgUploadBase.prototype, "uploadUrl", void 0);
334
+ __decorate([
335
+ property({ type: String })
336
+ ], ExmgUploadBase.prototype, "responseType", void 0);
337
+ __decorate([
338
+ property({ type: String })
339
+ ], ExmgUploadBase.prototype, "serverType", void 0);
340
+ __decorate([
341
+ property({ type: Object }),
342
+ observer(function (value) {
343
+ this._cropperConfig = { ...this._cropperConfig, ...value };
344
+ })
345
+ ], ExmgUploadBase.prototype, "cropperConfig", void 0);
346
+ __decorate([
347
+ state()
348
+ ], ExmgUploadBase.prototype, "_cropperConfig", void 0);
349
+ __decorate([
350
+ state()
351
+ ], ExmgUploadBase.prototype, "_isCropping", void 0);
352
+ __decorate([
353
+ property({ type: Boolean })
354
+ ], ExmgUploadBase.prototype, "isModeDialog", void 0);
355
+ __decorate([
356
+ state()
357
+ ], ExmgUploadBase.prototype, "_uploaded", void 0);
358
+ __decorate([
359
+ query('#crop-dialog')
360
+ ], ExmgUploadBase.prototype, "cropSection", void 0);
361
+ __decorate([
362
+ property({ type: Boolean })
363
+ ], ExmgUploadBase.prototype, "allowCropping", void 0);
364
+ __decorate([
365
+ property({ type: String })
366
+ ], ExmgUploadBase.prototype, "fixedResolution", void 0);
367
+ __decorate([
368
+ query('#file')
369
+ ], ExmgUploadBase.prototype, "fileElement", void 0);
370
+ __decorate([
371
+ query('.item-container')
372
+ ], ExmgUploadBase.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 ExmgUploadCropBase 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 ExmgUploadCropBase 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
+ ], ExmgUploadCropBase.prototype, "cropperConfig", void 0);
67
+ __decorate([
68
+ query('#image')
69
+ ], ExmgUploadCropBase.prototype, "cropArea", void 0);
70
+ __decorate([
71
+ property({ type: Boolean })
72
+ ], ExmgUploadCropBase.prototype, "hideActions", void 0);
73
+ __decorate([
74
+ state()
75
+ ], ExmgUploadCropBase.prototype, "_item", void 0);
76
+ //# sourceMappingURL=exm-upload-crop-base.js.map
@@ -0,0 +1,9 @@
1
+ import { ExmgUploadCropBase } from './exm-upload-crop-base.js';
2
+ export declare class ExmgUploadCrop extends ExmgUploadCropBase {
3
+ static styles: import("lit").CSSResult;
4
+ }
5
+ declare global {
6
+ interface HTMLElementTagNameMap {
7
+ 'exm-upload-crop': ExmgUploadCrop;
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 { ExmgUploadCropBase } from './exm-upload-crop-base.js';
5
+ let ExmgUploadCrop = class ExmgUploadCrop extends ExmgUploadCropBase {
6
+ };
7
+ ExmgUploadCrop.styles = style;
8
+ ExmgUploadCrop = __decorate([
9
+ customElement('exm-upload-crop')
10
+ ], ExmgUploadCrop);
11
+ export { ExmgUploadCrop };
12
+ //# sourceMappingURL=exm-upload-crop.js.map
@@ -0,0 +1,8 @@
1
+ import { ExmgElement } from '@exmg/lit-base';
2
+ declare const ExmgUploadDropAreaBase_base: (new (...args: any[]) => import("./mixins/exm-upload-drag-drop-mixin.js").DragAndDropInterface) & typeof ExmgElement;
3
+ export declare class ExmgUploadDropAreaBase extends ExmgUploadDropAreaBase_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 ExmgUploadDropAreaBase 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
+ ], ExmgUploadDropAreaBase.prototype, "description", void 0);
31
+ __decorate([
32
+ property({ type: Boolean })
33
+ ], ExmgUploadDropAreaBase.prototype, "disabled", void 0);
34
+ //# sourceMappingURL=exm-upload-drop-area-base.js.map
@@ -0,0 +1,9 @@
1
+ import { ExmgUploadDropAreaBase } from './exm-upload-drop-area-base.js';
2
+ export declare class ExmgUploadDropArea extends ExmgUploadDropAreaBase {
3
+ static styles: import("lit").CSSResult;
4
+ }
5
+ declare global {
6
+ interface HTMLElementTagNameMap {
7
+ 'exm-upload-drop-area': ExmgUploadDropArea;
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 { ExmgUploadDropAreaBase } from './exm-upload-drop-area-base.js';
5
+ let ExmgUploadDropArea = class ExmgUploadDropArea extends ExmgUploadDropAreaBase {
6
+ };
7
+ ExmgUploadDropArea.styles = style;
8
+ ExmgUploadDropArea = __decorate([
9
+ customElement('exm-upload-drop-area')
10
+ ], ExmgUploadDropArea);
11
+ export { ExmgUploadDropArea };
12
+ //# sourceMappingURL=exm-upload-drop-area.js.map
@@ -0,0 +1,15 @@
1
+ import { LitElement } from 'lit';
2
+ import '@exmg/exm-collapsed';
3
+ import { ExmgUpload } from './exm-upload.js';
4
+ export declare class ExmgUploadInput extends LitElement {
5
+ opened: boolean;
6
+ closeDelay: number;
7
+ static styles: import("lit").CSSResult[];
8
+ getUploadElement(): ExmgUpload;
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 ExmgUploadInput = class ExmgUploadInput 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
+ ExmgUploadInput.styles = [style];
74
+ __decorate([
75
+ property({ type: Boolean })
76
+ ], ExmgUploadInput.prototype, "opened", void 0);
77
+ __decorate([
78
+ property({ type: Number })
79
+ ], ExmgUploadInput.prototype, "closeDelay", void 0);
80
+ ExmgUploadInput = __decorate([
81
+ customElement('exm-upload-input')
82
+ ], ExmgUploadInput);
83
+ export { ExmgUploadInput };
84
+ //# sourceMappingURL=exm-upload-input.js.map