@devvit/ui-renderer 0.10.20-next-2024-04-26-62f55e1ef.0 → 0.10.20-next-2024-04-29-c515e730a.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/client/formbuilder/components/image-field/devvit-image-field.d.ts +24 -0
- package/client/formbuilder/components/image-field/devvit-image-field.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/devvit-image-field.js +158 -0
- package/client/formbuilder/components/image-field/drag-and-drop-controller.d.ts +19 -0
- package/client/formbuilder/components/image-field/drag-and-drop-controller.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/drag-and-drop-controller.js +113 -0
- package/client/formbuilder/components/image-field/media-controller.d.ts +59 -0
- package/client/formbuilder/components/image-field/media-controller.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/media-controller.js +207 -0
- package/client/formbuilder/components/image-field/render-empty-state.d.ts +15 -0
- package/client/formbuilder/components/image-field/render-empty-state.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/render-empty-state.js +46 -0
- package/client/formbuilder/components/image-field/render-loading-state.d.ts +9 -0
- package/client/formbuilder/components/image-field/render-loading-state.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/render-loading-state.js +27 -0
- package/client/formbuilder/components/image-field/render-media-carousel.d.ts +5 -0
- package/client/formbuilder/components/image-field/render-media-carousel.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/render-media-carousel.js +92 -0
- package/client/formbuilder/components/image-field/render-media-preview.d.ts +15 -0
- package/client/formbuilder/components/image-field/render-media-preview.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/render-media-preview.js +39 -0
- package/client/formbuilder/components/image-field/validate-image-size.d.ts +14 -0
- package/client/formbuilder/components/image-field/validate-image-size.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/validate-image-size.js +47 -0
- package/client/formbuilder/components/image-field/validateMedia.d.ts +13 -0
- package/client/formbuilder/components/image-field/validateMedia.d.ts.map +1 -0
- package/client/formbuilder/components/image-field/validateMedia.js +29 -0
- package/client/formbuilder/fields/renderFieldLabel.d.ts +1 -1
- package/client/formbuilder/fields/renderFieldLabel.d.ts.map +1 -1
- package/client/formbuilder/fields/renderFieldLabel.js +3 -1
- package/client/formbuilder/fields/renderFormFields.d.ts.map +1 -1
- package/client/formbuilder/fields/renderFormFields.js +2 -1
- package/client/formbuilder/fields/renderImageField.d.ts +5 -0
- package/client/formbuilder/fields/renderImageField.d.ts.map +1 -0
- package/client/formbuilder/fields/renderImageField.js +26 -0
- package/package.json +8 -8
- package/styles.js +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { InputElement } from '@reddit/faceplate/base-classes/input-element.js';
|
|
2
|
+
import { MediaController } from './media-controller.js';
|
|
3
|
+
import type { PropertyValueMap } from 'lit';
|
|
4
|
+
/**
|
|
5
|
+
* This entire file was copied from shreddit
|
|
6
|
+
* I removed some parts of it that were too "shreddit post creation" focused, but kept the original code style
|
|
7
|
+
* Eventually we will remove it in favour of faceplate-ui image upload component, but for now we have this
|
|
8
|
+
*/
|
|
9
|
+
export type UIType = 'mobile' | 'desktop';
|
|
10
|
+
export declare class DevvitFormImageField extends InputElement {
|
|
11
|
+
#private;
|
|
12
|
+
/** @ignore */
|
|
13
|
+
static get styles(): import("lit").CSSResultGroup[];
|
|
14
|
+
protected firstUpdated(_changedProperties: PropertyValueMap<unknown>): void;
|
|
15
|
+
fileInputInnerWrapper: HTMLDivElement;
|
|
16
|
+
mediaController: MediaController;
|
|
17
|
+
get value(): string;
|
|
18
|
+
set value(newValue: string);
|
|
19
|
+
_input?: HTMLInputElement;
|
|
20
|
+
handleRemoveClick: () => void;
|
|
21
|
+
formDisabledCallback(disabled: boolean): void;
|
|
22
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=devvit-image-field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devvit-image-field.d.ts","sourceRoot":"","sources":["../../../../../library/src/client/formbuilder/components/image-field/devvit-image-field.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,iDAAiD,CAAC;AAG/E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAMxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAE5C;;;;GAIG;AAEH,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1C,qBAAa,oBAAqB,SAAQ,YAAY;;IAMpD,cAAc;IACd,WAAoB,MAAM,mCAEzB;IAED,SAAS,CAAC,YAAY,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAAG,IAAI;IAO1C,qBAAqB,EAAG,cAAc,CAAC;IAIxE,eAAe,EAAE,eAAe,CAE7B;IAEH,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,KAAK,CAAC,QAAQ,EAJL,MAIK,EAEjB;IAID,MAAM,CAAC,EAAE,gBAAgB,CAAC;IA2B1B,iBAAiB,QAAO,IAAI,CAQ1B;IAeO,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAW7C,MAAM;CA0ChB"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
11
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
12
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
13
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
14
|
+
};
|
|
15
|
+
var _DevvitFormImageField_instances, _DevvitFormImageField_dragabble, _DevvitFormImageField_handleInput, _DevvitFormImageField_handleError, _DevvitFormImageField_setRequiredFieldError, _DevvitFormImageField_handleInputWrapperClick;
|
|
16
|
+
import { html } from 'lit';
|
|
17
|
+
import { property, query } from 'lit/decorators.js';
|
|
18
|
+
import { msg } from '@lit/localize';
|
|
19
|
+
import { InputElement } from '@reddit/faceplate/base-classes/input-element.js';
|
|
20
|
+
import { DragAndDropController, DragState } from './drag-and-drop-controller.js';
|
|
21
|
+
import { MediaController } from './media-controller.js';
|
|
22
|
+
import { renderEmptyState } from './render-empty-state.js';
|
|
23
|
+
import { renderCarousel } from './render-media-carousel.js';
|
|
24
|
+
import { ALLOWED_IMAGE_MIMETYPES } from './validateMedia.js';
|
|
25
|
+
import { styles } from '../../../../styles.js';
|
|
26
|
+
export class DevvitFormImageField extends InputElement {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
29
|
+
_DevvitFormImageField_instances.add(this);
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
_DevvitFormImageField_dragabble.set(this, new DragAndDropController(this, (files) => {
|
|
32
|
+
void this.mediaController.handleMedia(files);
|
|
33
|
+
}));
|
|
34
|
+
this.mediaController = new MediaController(this, {
|
|
35
|
+
setValidation: (message) => __classPrivateFieldGet(this, _DevvitFormImageField_instances, "m", _DevvitFormImageField_handleError).call(this, message),
|
|
36
|
+
});
|
|
37
|
+
this.handleRemoveClick = () => {
|
|
38
|
+
this.mediaController.media = [];
|
|
39
|
+
if (!this.mediaController.media.length) {
|
|
40
|
+
__classPrivateFieldGet(this, _DevvitFormImageField_instances, "m", _DevvitFormImageField_setRequiredFieldError).call(this);
|
|
41
|
+
}
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
this.requestUpdate();
|
|
44
|
+
};
|
|
45
|
+
_DevvitFormImageField_handleInputWrapperClick.set(this, async (event) => {
|
|
46
|
+
const target = event.target;
|
|
47
|
+
const button = target.closest('button.action');
|
|
48
|
+
if (!button) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (button.classList.contains('remove')) {
|
|
52
|
+
this.handleRemoveClick();
|
|
53
|
+
}
|
|
54
|
+
else if (button.classList.contains('upload-media')) {
|
|
55
|
+
this._input?.click();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/** @ignore */
|
|
60
|
+
static get styles() {
|
|
61
|
+
return [styles, super.styles];
|
|
62
|
+
}
|
|
63
|
+
firstUpdated(_changedProperties) {
|
|
64
|
+
// @ts-ignore
|
|
65
|
+
super.firstUpdated(_changedProperties);
|
|
66
|
+
__classPrivateFieldGet(this, _DevvitFormImageField_dragabble, "f").initEventListeners(this.fileInputInnerWrapper);
|
|
67
|
+
}
|
|
68
|
+
get value() {
|
|
69
|
+
return this.mediaController.getValue();
|
|
70
|
+
}
|
|
71
|
+
set value(newValue) {
|
|
72
|
+
this.mediaController.setValue(newValue);
|
|
73
|
+
}
|
|
74
|
+
formDisabledCallback(disabled) {
|
|
75
|
+
if (disabled) {
|
|
76
|
+
// @ts-ignore
|
|
77
|
+
this.setCustomValidity('');
|
|
78
|
+
}
|
|
79
|
+
else if (!disabled && this.value?.length === 0) {
|
|
80
|
+
__classPrivateFieldGet(this, _DevvitFormImageField_instances, "m", _DevvitFormImageField_setRequiredFieldError).call(this);
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
this.reportValidity();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
render() {
|
|
86
|
+
const mimetypes = ALLOWED_IMAGE_MIMETYPES;
|
|
87
|
+
/* eslint-disable @reddit/i18n-shreddit/no-unwrapped-strings */
|
|
88
|
+
let containerClasses = `border-neutral-border ${this.mediaController.media.length ? 'border-solid' : 'border-dashed'}`;
|
|
89
|
+
if (__classPrivateFieldGet(this, _DevvitFormImageField_dragabble, "f").dragState === DragState.IN_WINDOW) {
|
|
90
|
+
containerClasses = 'bg-neutral-background-weak border-alienblue-600 border-dashed';
|
|
91
|
+
}
|
|
92
|
+
else if (__classPrivateFieldGet(this, _DevvitFormImageField_dragabble, "f").dragState === DragState.IN_FRAME) {
|
|
93
|
+
containerClasses = 'bg-neutral-background-weak border-alienblue-600 border-solid';
|
|
94
|
+
}
|
|
95
|
+
/* eslint-enable @reddit/i18n-shreddit/no-unwrapped-strings */
|
|
96
|
+
const HiddenInput = html `
|
|
97
|
+
<input
|
|
98
|
+
class="file-input"
|
|
99
|
+
hidden
|
|
100
|
+
type="file"
|
|
101
|
+
@input="${__classPrivateFieldGet(this, _DevvitFormImageField_instances, "m", _DevvitFormImageField_handleInput)}"
|
|
102
|
+
accept="${mimetypes.join(',')}"
|
|
103
|
+
/>
|
|
104
|
+
`;
|
|
105
|
+
return html `
|
|
106
|
+
${HiddenInput}
|
|
107
|
+
<div
|
|
108
|
+
id="fileInputInnerWrapper"
|
|
109
|
+
class="flex w-full border-sm rounded-dx-md overflow-hidden group min-h-[min(20vw,150px)] ${containerClasses}"
|
|
110
|
+
@click="${__classPrivateFieldGet(this, _DevvitFormImageField_handleInputWrapperClick, "f")}"
|
|
111
|
+
@keypress="${__classPrivateFieldGet(this, _DevvitFormImageField_handleInputWrapperClick, "f")}"
|
|
112
|
+
>
|
|
113
|
+
${this.mediaController.media.length
|
|
114
|
+
? renderCarousel(this.mediaController)
|
|
115
|
+
: renderEmptyState({
|
|
116
|
+
allowImages: true,
|
|
117
|
+
allowVideos: false,
|
|
118
|
+
inputDragState: __classPrivateFieldGet(this, _DevvitFormImageField_dragabble, "f").dragState,
|
|
119
|
+
})}
|
|
120
|
+
</div>
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
_DevvitFormImageField_dragabble = new WeakMap(), _DevvitFormImageField_handleInputWrapperClick = new WeakMap(), _DevvitFormImageField_instances = new WeakSet(), _DevvitFormImageField_handleInput = function _DevvitFormImageField_handleInput(e) {
|
|
125
|
+
if (!(e.target instanceof HTMLInputElement))
|
|
126
|
+
return;
|
|
127
|
+
const files = e.target.files;
|
|
128
|
+
if (files?.length) {
|
|
129
|
+
void this.mediaController.handleMedia(Array.from(files));
|
|
130
|
+
e.target.value = '';
|
|
131
|
+
}
|
|
132
|
+
}, _DevvitFormImageField_handleError = function _DevvitFormImageField_handleError(error) {
|
|
133
|
+
// @ts-ignore
|
|
134
|
+
this.setCustomValidity(error);
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
this.reportValidity();
|
|
137
|
+
}, _DevvitFormImageField_setRequiredFieldError = function _DevvitFormImageField_setRequiredFieldError() {
|
|
138
|
+
__classPrivateFieldGet(this, _DevvitFormImageField_instances, "m", _DevvitFormImageField_handleError).call(this, msg('Please add an image', {
|
|
139
|
+
desc: 'Message to user to please add an image file',
|
|
140
|
+
}));
|
|
141
|
+
};
|
|
142
|
+
__decorate([
|
|
143
|
+
query('#fileInputInnerWrapper'),
|
|
144
|
+
__metadata("design:type", HTMLDivElement)
|
|
145
|
+
], DevvitFormImageField.prototype, "fileInputInnerWrapper", void 0);
|
|
146
|
+
__decorate([
|
|
147
|
+
property({ type: MediaController })
|
|
148
|
+
// @ts-ignore
|
|
149
|
+
,
|
|
150
|
+
__metadata("design:type", MediaController)
|
|
151
|
+
], DevvitFormImageField.prototype, "mediaController", void 0);
|
|
152
|
+
__decorate([
|
|
153
|
+
query('input.file-input'),
|
|
154
|
+
__metadata("design:type", HTMLInputElement)
|
|
155
|
+
], DevvitFormImageField.prototype, "_input", void 0);
|
|
156
|
+
// Faceplate's base classes and mixins aren't playing nice with type checking for some reason
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
158
|
+
customElements.define('devvit-form-image-field', DevvitFormImageField);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* This entire file was copied from shreddit
|
|
4
|
+
* I removed some parts of it that were too "shreddit post creation" focused, but kept the original code style
|
|
5
|
+
* Eventually we will remove it in favour of faceplate-ui image upload component, but for now we have this
|
|
6
|
+
*/
|
|
7
|
+
export declare enum DragState {
|
|
8
|
+
IDLE = "IDLE",
|
|
9
|
+
IN_WINDOW = "IN_WINDOW",
|
|
10
|
+
IN_FRAME = "IN_FRAME"
|
|
11
|
+
}
|
|
12
|
+
export declare class DragAndDropController implements ReactiveController {
|
|
13
|
+
#private;
|
|
14
|
+
dragState: DragState;
|
|
15
|
+
constructor(host: ReactiveControllerHost, handleDrop: (files: File[]) => void);
|
|
16
|
+
hostDisconnected(): void;
|
|
17
|
+
initEventListeners(component: HTMLElement): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=drag-and-drop-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drag-and-drop-controller.d.ts","sourceRoot":"","sources":["../../../../../library/src/client/formbuilder/components/image-field/drag-and-drop-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,KAAK,CAAC;AAEtE;;;;GAIG;AAEH,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,QAAQ,aAAa;CACtB;AAED,qBAAa,qBAAsB,YAAW,kBAAkB;;IAK9D,SAAS,EAAE,SAAS,CAAkB;gBAE1B,IAAI,EAAE,sBAAsB,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI;IAa7E,gBAAgB,IAAI,IAAI;IAIjB,kBAAkB,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI;CAkExD"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _DragAndDropController_instances, _DragAndDropController_component, _DragAndDropController_handleDrop, _DragAndDropController_host, _DragAndDropController_disposeEventListeners, _DragAndDropController_onComponentDragEnter, _DragAndDropController_onComponentDrop, _DragAndDropController_onWindowDragEnter, _DragAndDropController_onWindowDragLeave, _DragAndDropController_onWindowDragOver;
|
|
13
|
+
/**
|
|
14
|
+
* This entire file was copied from shreddit
|
|
15
|
+
* I removed some parts of it that were too "shreddit post creation" focused, but kept the original code style
|
|
16
|
+
* Eventually we will remove it in favour of faceplate-ui image upload component, but for now we have this
|
|
17
|
+
*/
|
|
18
|
+
export var DragState;
|
|
19
|
+
(function (DragState) {
|
|
20
|
+
DragState["IDLE"] = "IDLE";
|
|
21
|
+
DragState["IN_WINDOW"] = "IN_WINDOW";
|
|
22
|
+
DragState["IN_FRAME"] = "IN_FRAME";
|
|
23
|
+
})(DragState || (DragState = {}));
|
|
24
|
+
export class DragAndDropController {
|
|
25
|
+
constructor(host, handleDrop) {
|
|
26
|
+
_DragAndDropController_instances.add(this);
|
|
27
|
+
_DragAndDropController_component.set(this, null);
|
|
28
|
+
_DragAndDropController_handleDrop.set(this, void 0);
|
|
29
|
+
_DragAndDropController_host.set(this, void 0);
|
|
30
|
+
this.dragState = DragState.IDLE;
|
|
31
|
+
_DragAndDropController_onComponentDragEnter.set(this, (e) => {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
this.dragState = DragState.IN_FRAME;
|
|
35
|
+
__classPrivateFieldGet(this, _DragAndDropController_host, "f").requestUpdate();
|
|
36
|
+
});
|
|
37
|
+
_DragAndDropController_onComponentDrop.set(this, (e) => {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
if (e.dataTransfer) {
|
|
40
|
+
const files = getFilesFromDataTransfer(e.dataTransfer);
|
|
41
|
+
__classPrivateFieldGet(this, _DragAndDropController_handleDrop, "f").call(this, files);
|
|
42
|
+
}
|
|
43
|
+
this.dragState = DragState.IDLE;
|
|
44
|
+
__classPrivateFieldGet(this, _DragAndDropController_host, "f").requestUpdate();
|
|
45
|
+
});
|
|
46
|
+
_DragAndDropController_onWindowDragEnter.set(this, (e) => {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
this.dragState = DragState.IN_WINDOW;
|
|
49
|
+
__classPrivateFieldGet(this, _DragAndDropController_host, "f").requestUpdate();
|
|
50
|
+
});
|
|
51
|
+
_DragAndDropController_onWindowDragLeave.set(this, (e) => {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
if (!e.relatedTarget || e.relatedTarget === document.body) {
|
|
54
|
+
this.dragState = DragState.IDLE;
|
|
55
|
+
__classPrivateFieldGet(this, _DragAndDropController_host, "f").requestUpdate();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
_DragAndDropController_onWindowDragOver.set(this, (e) => {
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
});
|
|
61
|
+
__classPrivateFieldSet(this, _DragAndDropController_handleDrop, handleDrop, "f");
|
|
62
|
+
__classPrivateFieldSet(this, _DragAndDropController_host, host, "f");
|
|
63
|
+
host.addController(this);
|
|
64
|
+
// Bind event handlers to ensure the correct 'this' context
|
|
65
|
+
__classPrivateFieldSet(this, _DragAndDropController_onComponentDragEnter, __classPrivateFieldGet(this, _DragAndDropController_onComponentDragEnter, "f").bind(this), "f");
|
|
66
|
+
__classPrivateFieldSet(this, _DragAndDropController_onComponentDrop, __classPrivateFieldGet(this, _DragAndDropController_onComponentDrop, "f").bind(this), "f");
|
|
67
|
+
__classPrivateFieldSet(this, _DragAndDropController_onWindowDragEnter, __classPrivateFieldGet(this, _DragAndDropController_onWindowDragEnter, "f").bind(this), "f");
|
|
68
|
+
__classPrivateFieldSet(this, _DragAndDropController_onWindowDragLeave, __classPrivateFieldGet(this, _DragAndDropController_onWindowDragLeave, "f").bind(this), "f");
|
|
69
|
+
__classPrivateFieldSet(this, _DragAndDropController_onWindowDragOver, __classPrivateFieldGet(this, _DragAndDropController_onWindowDragOver, "f").bind(this), "f");
|
|
70
|
+
}
|
|
71
|
+
hostDisconnected() {
|
|
72
|
+
__classPrivateFieldGet(this, _DragAndDropController_instances, "m", _DragAndDropController_disposeEventListeners).call(this);
|
|
73
|
+
}
|
|
74
|
+
initEventListeners(component) {
|
|
75
|
+
__classPrivateFieldSet(this, _DragAndDropController_component, component, "f");
|
|
76
|
+
this.dragState = DragState.IDLE;
|
|
77
|
+
__classPrivateFieldGet(this, _DragAndDropController_host, "f").requestUpdate();
|
|
78
|
+
// Component-specific events
|
|
79
|
+
__classPrivateFieldGet(this, _DragAndDropController_component, "f").addEventListener('dragover', __classPrivateFieldGet(this, _DragAndDropController_onComponentDragEnter, "f"));
|
|
80
|
+
__classPrivateFieldGet(this, _DragAndDropController_component, "f").addEventListener('drop', __classPrivateFieldGet(this, _DragAndDropController_onComponentDrop, "f"));
|
|
81
|
+
// Window-specific events
|
|
82
|
+
window.addEventListener('dragover', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragEnter, "f"));
|
|
83
|
+
window.addEventListener('dragleave', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragLeave, "f"));
|
|
84
|
+
window.addEventListener('drop', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragLeave, "f"));
|
|
85
|
+
window.addEventListener('dragover', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragOver, "f"));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
_DragAndDropController_component = new WeakMap(), _DragAndDropController_handleDrop = new WeakMap(), _DragAndDropController_host = new WeakMap(), _DragAndDropController_onComponentDragEnter = new WeakMap(), _DragAndDropController_onComponentDrop = new WeakMap(), _DragAndDropController_onWindowDragEnter = new WeakMap(), _DragAndDropController_onWindowDragLeave = new WeakMap(), _DragAndDropController_onWindowDragOver = new WeakMap(), _DragAndDropController_instances = new WeakSet(), _DragAndDropController_disposeEventListeners = function _DragAndDropController_disposeEventListeners() {
|
|
89
|
+
if (__classPrivateFieldGet(this, _DragAndDropController_component, "f")) {
|
|
90
|
+
__classPrivateFieldGet(this, _DragAndDropController_component, "f").removeEventListener('dragover', __classPrivateFieldGet(this, _DragAndDropController_onComponentDragEnter, "f"));
|
|
91
|
+
__classPrivateFieldGet(this, _DragAndDropController_component, "f").removeEventListener('drop', __classPrivateFieldGet(this, _DragAndDropController_onComponentDrop, "f"));
|
|
92
|
+
}
|
|
93
|
+
// Remove window-specific event listeners
|
|
94
|
+
window.removeEventListener('dragover', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragEnter, "f"));
|
|
95
|
+
window.removeEventListener('dragleave', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragLeave, "f"));
|
|
96
|
+
window.removeEventListener('drop', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragLeave, "f")); // Match with the correct event
|
|
97
|
+
window.removeEventListener('dragover', __classPrivateFieldGet(this, _DragAndDropController_onWindowDragOver, "f"));
|
|
98
|
+
this.dragState = DragState.IDLE;
|
|
99
|
+
__classPrivateFieldGet(this, _DragAndDropController_host, "f").requestUpdate();
|
|
100
|
+
};
|
|
101
|
+
const getFilesFromDataTransfer = (dataTransfer) => {
|
|
102
|
+
if (dataTransfer.items) {
|
|
103
|
+
return Array.from(dataTransfer.items)
|
|
104
|
+
.map((item) => (item.kind === 'file' ? item.getAsFile() : null))
|
|
105
|
+
.filter(Boolean);
|
|
106
|
+
}
|
|
107
|
+
else if (dataTransfer.files) {
|
|
108
|
+
return Array.from(dataTransfer.files);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ValidationResult } from './validateMedia.js';
|
|
2
|
+
import type { LitElement } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* This entire file was copied from shreddit
|
|
5
|
+
* I removed some parts of it that were too "shreddit post creation" focused, but kept the original code style
|
|
6
|
+
* Eventually we will remove it in favour of faceplate-ui image upload component, but for now we have this
|
|
7
|
+
*/
|
|
8
|
+
interface UploadResponse {
|
|
9
|
+
url?: string;
|
|
10
|
+
mediaId?: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
export type MediaValue = {
|
|
14
|
+
mediaId: string;
|
|
15
|
+
url: string;
|
|
16
|
+
caption?: string;
|
|
17
|
+
outboundUrl?: string;
|
|
18
|
+
posterUrl?: string;
|
|
19
|
+
isGif?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type MediaItem = {
|
|
22
|
+
id: string;
|
|
23
|
+
file?: File;
|
|
24
|
+
type?: 'still' | 'video';
|
|
25
|
+
src?: string;
|
|
26
|
+
posterSrc?: string;
|
|
27
|
+
status?: MediaStatus;
|
|
28
|
+
validationResult?: ValidationResult;
|
|
29
|
+
mediaResponse?: Promise<UploadResponse>;
|
|
30
|
+
posterResponse?: Promise<UploadResponse>;
|
|
31
|
+
value?: MediaValue;
|
|
32
|
+
width?: number;
|
|
33
|
+
height?: number;
|
|
34
|
+
};
|
|
35
|
+
export declare enum MediaStatus {
|
|
36
|
+
loading = "loading",
|
|
37
|
+
success = "success"
|
|
38
|
+
}
|
|
39
|
+
export declare enum PostType {
|
|
40
|
+
image = "image"
|
|
41
|
+
}
|
|
42
|
+
type ValidationCallback = (message: string) => void;
|
|
43
|
+
type MediaControllerOptions = {
|
|
44
|
+
setValidation?: ValidationCallback;
|
|
45
|
+
};
|
|
46
|
+
export declare const MAX_FILE_COUNT = 20;
|
|
47
|
+
export declare class MediaController {
|
|
48
|
+
#private;
|
|
49
|
+
media: MediaItem[];
|
|
50
|
+
constructor(host: LitElement, options?: MediaControllerOptions);
|
|
51
|
+
getValue(): string;
|
|
52
|
+
setValue(newValue: string): void;
|
|
53
|
+
handleMedia(files: File[]): Promise<void>;
|
|
54
|
+
getPostType(): PostType;
|
|
55
|
+
hasLoadingMedia(): boolean;
|
|
56
|
+
removeMedia(index: number): void;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=media-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-controller.d.ts","sourceRoot":"","sources":["../../../../../library/src/client/formbuilder/components/image-field/media-controller.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtC;;;;GAIG;AAGH,UAAU,cAAc;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,OAAO,YAAY;CACpB;AAED,oBAAY,QAAQ;IAClB,KAAK,UAAU;CAChB;AAED,KAAK,kBAAkB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpD,KAAK,sBAAsB,GAAG;IAC5B,aAAa,CAAC,EAAE,kBAAkB,CAAC;CACpC,CAAC;AAEF,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,qBAAa,eAAe;;IAC1B,KAAK,EAAE,SAAS,EAAE,CAAM;gBAKZ,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,sBAAsB;IAK9D,QAAQ,IAAI,MAAM;IAQlB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAmB1B,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA4H/C,WAAW,IAAI,QAAQ;IAIvB,eAAe,IAAI,OAAO;IA0D1B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAGjC"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _MediaController_instances, _MediaController_host, _MediaController_setValidation, _MediaController_getRandomId, _MediaController_fireChangeEvent, _MediaController_handleImageResponse, _MediaController_handleImage, _MediaController_upload, _MediaController_createMediaItem, _MediaController_createImage, _MediaController_isVideo, _MediaController_dispatchAlert, _MediaController_filterValidFiles, _MediaController_getDefaultErrorMessage, _MediaController_handleError;
|
|
13
|
+
import { customEvent } from '@reddit/faceplate/lib/custom-event.js';
|
|
14
|
+
import { msg } from '@lit/localize';
|
|
15
|
+
import { ALLOWED_VIDEO_MIMETYPES, validateImageFile } from './validateMedia.js';
|
|
16
|
+
export var MediaStatus;
|
|
17
|
+
(function (MediaStatus) {
|
|
18
|
+
MediaStatus["loading"] = "loading";
|
|
19
|
+
MediaStatus["success"] = "success";
|
|
20
|
+
})(MediaStatus || (MediaStatus = {}));
|
|
21
|
+
export var PostType;
|
|
22
|
+
(function (PostType) {
|
|
23
|
+
PostType["image"] = "image";
|
|
24
|
+
})(PostType || (PostType = {}));
|
|
25
|
+
export const MAX_FILE_COUNT = 20;
|
|
26
|
+
export class MediaController {
|
|
27
|
+
constructor(host, options) {
|
|
28
|
+
_MediaController_instances.add(this);
|
|
29
|
+
this.media = [];
|
|
30
|
+
_MediaController_host.set(this, void 0);
|
|
31
|
+
_MediaController_setValidation.set(this, void 0);
|
|
32
|
+
__classPrivateFieldSet(this, _MediaController_host, host, "f");
|
|
33
|
+
__classPrivateFieldSet(this, _MediaController_setValidation, options?.setValidation ?? (() => { }), "f");
|
|
34
|
+
}
|
|
35
|
+
getValue() {
|
|
36
|
+
const validFiles = this.media.filter((media) => media.status === MediaStatus.success);
|
|
37
|
+
if (validFiles.length === 0) {
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
return JSON.stringify(validFiles.map((media) => media.value));
|
|
41
|
+
}
|
|
42
|
+
setValue(newValue) {
|
|
43
|
+
const val = JSON.parse(newValue);
|
|
44
|
+
this.media = val;
|
|
45
|
+
}
|
|
46
|
+
async handleMedia(files) {
|
|
47
|
+
try {
|
|
48
|
+
const seed = this.media.length;
|
|
49
|
+
__classPrivateFieldGet(this, _MediaController_setValidation, "f").call(this, '');
|
|
50
|
+
const validFiles = __classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_filterValidFiles).call(this, files);
|
|
51
|
+
if (validFiles.length > 0) {
|
|
52
|
+
const mediaItems = [];
|
|
53
|
+
for (const file of validFiles) {
|
|
54
|
+
mediaItems.push(__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_handleImage).call(this, file));
|
|
55
|
+
}
|
|
56
|
+
this.media = this.media.concat(mediaItems);
|
|
57
|
+
__classPrivateFieldGet(this, _MediaController_host, "f").requestUpdate('mediaLength', seed);
|
|
58
|
+
const mediaResponse = await Promise.all(mediaItems.map((item) => item.mediaResponse));
|
|
59
|
+
__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_handleImageResponse).call(this, mediaResponse, seed);
|
|
60
|
+
__classPrivateFieldGet(this, _MediaController_host, "f").requestUpdate();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (!(error instanceof Error)) {
|
|
65
|
+
console.error(error);
|
|
66
|
+
__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_handleError).call(this, msg('Something went wrong. Please try again later', {
|
|
67
|
+
desc: 'Unknown error uploading the file',
|
|
68
|
+
}));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_handleError).call(this, error.message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
getPostType() {
|
|
75
|
+
return PostType.image;
|
|
76
|
+
}
|
|
77
|
+
hasLoadingMedia() {
|
|
78
|
+
return this.media.some((media) => media.status === MediaStatus.loading);
|
|
79
|
+
}
|
|
80
|
+
removeMedia(index) {
|
|
81
|
+
this.media.splice(index, 1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
_MediaController_host = new WeakMap(), _MediaController_setValidation = new WeakMap(), _MediaController_instances = new WeakSet(), _MediaController_getRandomId = function _MediaController_getRandomId(filename) {
|
|
85
|
+
// match all temporary media IDs with that filename
|
|
86
|
+
// eslint-disable-next-line @reddit/i18n-shreddit/no-unwrapped-strings, security/detect-non-literal-regexp
|
|
87
|
+
const regex = new RegExp(`^${filename}-(?<id>\\d+)$`);
|
|
88
|
+
// find the highest suffix and increment it by one
|
|
89
|
+
const suffix = 1 +
|
|
90
|
+
this.media.reduce((currSuffix, media) => {
|
|
91
|
+
const match = media.id.match(regex);
|
|
92
|
+
return match ? Math.max(currSuffix, parseInt(match.groups.id, 10)) : currSuffix;
|
|
93
|
+
}, -1);
|
|
94
|
+
return `${filename}-${suffix}`;
|
|
95
|
+
}, _MediaController_fireChangeEvent = function _MediaController_fireChangeEvent() {
|
|
96
|
+
// eslint-disable-next-line @reddit/i18n-shreddit/no-unwrapped-strings
|
|
97
|
+
const event = new Event('change', { bubbles: true });
|
|
98
|
+
__classPrivateFieldGet(this, _MediaController_host, "f").dispatchEvent(event);
|
|
99
|
+
}, _MediaController_handleImageResponse = function _MediaController_handleImageResponse(mediaResponses, seed) {
|
|
100
|
+
__classPrivateFieldGet(this, _MediaController_host, "f").setAttribute('name', 'image');
|
|
101
|
+
let success = false;
|
|
102
|
+
const failedItemsIndexes = [];
|
|
103
|
+
for (const [i, mediaResponse] of mediaResponses.entries()) {
|
|
104
|
+
const index = seed + i;
|
|
105
|
+
const { url, mediaId, error = null } = mediaResponse ?? {};
|
|
106
|
+
const media = this.media[index];
|
|
107
|
+
if (url && mediaId) {
|
|
108
|
+
const galleryItem = { mediaId, url };
|
|
109
|
+
media.id = mediaId;
|
|
110
|
+
media.value = galleryItem;
|
|
111
|
+
media.status = MediaStatus.success;
|
|
112
|
+
success = true;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_dispatchAlert).call(this, error);
|
|
116
|
+
failedItemsIndexes.push(index);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (failedItemsIndexes.length > 0) {
|
|
120
|
+
this.media = this.media.filter((_, index) => !failedItemsIndexes.includes(index));
|
|
121
|
+
}
|
|
122
|
+
if (success) {
|
|
123
|
+
__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_fireChangeEvent).call(this);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
__classPrivateFieldGet(this, _MediaController_host, "f").requestUpdate('mediaLength', this.media.length - 1);
|
|
127
|
+
}
|
|
128
|
+
}, _MediaController_handleImage = function _MediaController_handleImage(file) {
|
|
129
|
+
const IMAGE_UPLOAD_ERROR = msg('Unable to upload image', {
|
|
130
|
+
desc: 'Error: unable to upload image file',
|
|
131
|
+
});
|
|
132
|
+
const mediaItem = __classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_createImage).call(this, file);
|
|
133
|
+
const validation = validateImageFile(file);
|
|
134
|
+
if (!validation.valid) {
|
|
135
|
+
mediaItem.mediaResponse = Promise.resolve({
|
|
136
|
+
error: validation.error ?? IMAGE_UPLOAD_ERROR,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
mediaItem.mediaResponse = __classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_upload).call(this, file);
|
|
141
|
+
}
|
|
142
|
+
return mediaItem;
|
|
143
|
+
}, _MediaController_upload = async function _MediaController_upload(blob) {
|
|
144
|
+
console.log('UPLOAD HAPPENS');
|
|
145
|
+
const imageUploadEvent = customEvent('devvit-image-upload', {
|
|
146
|
+
blob,
|
|
147
|
+
uploadResponse: null,
|
|
148
|
+
});
|
|
149
|
+
__classPrivateFieldGet(this, _MediaController_host, "f").dispatchEvent(imageUploadEvent);
|
|
150
|
+
const response = await imageUploadEvent.detail.uploadResponse;
|
|
151
|
+
if (!response) {
|
|
152
|
+
return Promise.resolve({
|
|
153
|
+
error: 'Image upload failed',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return response;
|
|
157
|
+
}, _MediaController_createMediaItem = function _MediaController_createMediaItem(file) {
|
|
158
|
+
const src = URL.createObjectURL(file);
|
|
159
|
+
return {
|
|
160
|
+
id: __classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_getRandomId).call(this, file.name),
|
|
161
|
+
file,
|
|
162
|
+
src,
|
|
163
|
+
status: MediaStatus.loading,
|
|
164
|
+
};
|
|
165
|
+
}, _MediaController_createImage = function _MediaController_createImage(file) {
|
|
166
|
+
return {
|
|
167
|
+
...__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_createMediaItem).call(this, file),
|
|
168
|
+
type: 'still',
|
|
169
|
+
};
|
|
170
|
+
}, _MediaController_isVideo = function _MediaController_isVideo(file) {
|
|
171
|
+
if (!file)
|
|
172
|
+
return false;
|
|
173
|
+
return ALLOWED_VIDEO_MIMETYPES.includes(file.type);
|
|
174
|
+
}, _MediaController_dispatchAlert = function _MediaController_dispatchAlert(message) {
|
|
175
|
+
__classPrivateFieldGet(this, _MediaController_host, "f").dispatchEvent(customEvent('faceplate-alert', {
|
|
176
|
+
level: 4, // warning
|
|
177
|
+
message: message ?? __classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_getDefaultErrorMessage).call(this),
|
|
178
|
+
}));
|
|
179
|
+
}, _MediaController_filterValidFiles = function _MediaController_filterValidFiles(files) {
|
|
180
|
+
let mediaFiles = files;
|
|
181
|
+
const hasVideoInSelectedFiles = files.some((file) => __classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_isVideo).call(this, file));
|
|
182
|
+
const isMultipleSelection = files.length > 1;
|
|
183
|
+
const isValidMediaPresent = this.media.length > 0;
|
|
184
|
+
if (isMultipleSelection || isValidMediaPresent) {
|
|
185
|
+
const GALLERY_NOT_ALLOWED_ERROR = msg(`Only one file can be used for the image input`, {
|
|
186
|
+
desc: 'Error: Multiple files cannot be added to image input',
|
|
187
|
+
});
|
|
188
|
+
__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_dispatchAlert).call(this, GALLERY_NOT_ALLOWED_ERROR);
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
if (hasVideoInSelectedFiles && (isValidMediaPresent || isMultipleSelection)) {
|
|
192
|
+
const GALLERY_CONTAIN_VIDEO_ERROR = msg('Image input can only contain images', {
|
|
193
|
+
desc: 'Error when users upload non-image media files to image input',
|
|
194
|
+
});
|
|
195
|
+
__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_dispatchAlert).call(this, GALLERY_CONTAIN_VIDEO_ERROR);
|
|
196
|
+
mediaFiles = files.filter((file) => !__classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_isVideo).call(this, file));
|
|
197
|
+
}
|
|
198
|
+
return mediaFiles;
|
|
199
|
+
}, _MediaController_getDefaultErrorMessage = function _MediaController_getDefaultErrorMessage() {
|
|
200
|
+
return msg('There was an error uploading the file', {
|
|
201
|
+
desc: 'Generic error message when file upload fails',
|
|
202
|
+
id: 'generic-error-message-for-uploading-file',
|
|
203
|
+
});
|
|
204
|
+
}, _MediaController_handleError = function _MediaController_handleError(err) {
|
|
205
|
+
const error = err || __classPrivateFieldGet(this, _MediaController_instances, "m", _MediaController_getDefaultErrorMessage).call(this);
|
|
206
|
+
__classPrivateFieldGet(this, _MediaController_setValidation, "f").call(this, error);
|
|
207
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TemplateResult } from 'lit';
|
|
2
|
+
import { DragState } from './drag-and-drop-controller.js';
|
|
3
|
+
/**
|
|
4
|
+
* This entire file was copied from shreddit
|
|
5
|
+
* I removed some parts of it that were too "shreddit post creation" focused, but kept the original code style
|
|
6
|
+
* Eventually we will remove it in favour of faceplate-ui image upload component, but for now we have this
|
|
7
|
+
*/
|
|
8
|
+
interface RenderEmptyStateProps {
|
|
9
|
+
allowImages: boolean;
|
|
10
|
+
allowVideos: boolean;
|
|
11
|
+
inputDragState: DragState;
|
|
12
|
+
}
|
|
13
|
+
export declare function renderEmptyState({ allowImages, allowVideos, inputDragState, }: RenderEmptyStateProps): TemplateResult<1>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=render-empty-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-empty-state.d.ts","sourceRoot":"","sources":["../../../../../library/src/client/formbuilder/components/image-field/render-empty-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D;;;;GAIG;AAEH,UAAU,qBAAqB;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,SAAS,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,WAAW,EACX,WAAW,EACX,cAAc,GACf,EAAE,qBAAqB,GAAG,cAAc,CAAC,CAAC,CAAC,CAuC3C"}
|