@mmlogic/components 0.5.2 → 0.5.4
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/dist/cjs/{cell-renderer-CmaO0CZT.js → cell-renderer-Coy-aD3k.js} +146 -1
- package/dist/cjs/{client-layout-RZ3Ix-4a.js → client-layout-CqVuJumR.js} +9 -0
- package/dist/cjs/{index-DzRfoAPz.js → index-DVbdkYO3.js} +468 -6
- package/dist/cjs/index.cjs.js +4 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/mosterdcomponents.cjs.js +2 -2
- package/dist/cjs/{mrd-boolean-field_23.cjs.entry.js → mrd-boolean-field_25.cjs.entry.js} +5696 -5229
- package/dist/cjs/mrd-merge-view.cjs.entry.js +5 -5
- package/dist/collection/collection-manifest.json +2 -0
- package/dist/collection/components/documents/mrd-document-container/mrd-document-container.css +3 -0
- package/dist/collection/components/documents/mrd-document-container/mrd-document-container.js +23 -3
- package/dist/collection/components/documents/mrd-document-list/mrd-document-list.js +76 -2
- package/dist/collection/components/documents/mrd-document-view/mrd-document-view.js +7 -8
- package/dist/collection/components/email/mrd-email-view/mrd-email-view.css +126 -0
- package/dist/collection/components/email/mrd-email-view/mrd-email-view.js +247 -0
- package/dist/collection/components/fields/file-upload-common.js +23 -7
- package/dist/collection/components/fields/mrd-boolean-field/mrd-boolean-field.js +1 -1
- package/dist/collection/components/fields/mrd-currency-field/mrd-currency-field.js +1 -1
- package/dist/collection/components/fields/mrd-date-field/mrd-date-field.js +1 -1
- package/dist/collection/components/fields/mrd-datetime-field/mrd-datetime-field.js +1 -1
- package/dist/collection/components/fields/mrd-email-field/mrd-email-field.js +1 -1
- package/dist/collection/components/fields/mrd-file-field/mrd-file-field.css +20 -1
- package/dist/collection/components/fields/mrd-file-field/mrd-file-field.js +108 -47
- package/dist/collection/components/fields/mrd-image-field/mrd-image-field.css +44 -0
- package/dist/collection/components/fields/mrd-image-field/mrd-image-field.js +126 -58
- package/dist/collection/components/fields/mrd-longtext-field/mrd-longtext-field.js +1 -1
- package/dist/collection/components/fields/mrd-number-field/mrd-number-field.js +1 -1
- package/dist/collection/components/fields/mrd-relation-field/mrd-relation-field.js +13 -3
- package/dist/collection/components/fields/mrd-secret-field/mrd-secret-field.js +2 -2
- package/dist/collection/components/fields/mrd-text-field/mrd-text-field.js +1 -1
- package/dist/collection/components/fields/mrd-textarea-field/mrd-textarea-field.js +1 -1
- package/dist/collection/components/fields/mrd-time-field/mrd-time-field.js +1 -1
- package/dist/collection/components/form/mrd-field/mrd-field.js +5 -5
- package/dist/collection/components/form/mrd-form/mrd-form.js +63 -10
- package/dist/collection/components/invoice/mrd-invoice-view/mrd-invoice-view.css +145 -0
- package/dist/collection/components/invoice/mrd-invoice-view/mrd-invoice-view.js +281 -0
- package/dist/collection/components/layout/mrd-layout-section/field-value.js +9 -3
- package/dist/collection/components/layout/mrd-layout-section/layout-helpers.js +6 -0
- package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.css +14 -0
- package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +45 -15
- package/dist/collection/components/merge/mrd-merge-view/mrd-merge-view.js +2 -2
- package/dist/collection/dev/api.js +20 -5
- package/dist/collection/dev/app.js +51 -13
- package/dist/collection/dev/example-data.js +132 -3
- package/dist/collection/types/client-layout.js +6 -0
- package/dist/collection/utils/document-attachments.js +27 -14
- package/dist/collection/utils/i18n.js +144 -0
- package/dist/components/cell-renderer.js +1 -1
- package/dist/components/client-layout.js +1 -1
- package/dist/components/document-attachments.js +1 -1
- package/dist/components/file-upload-common.js +1 -1
- package/dist/components/format.js +1 -1
- package/dist/components/i18n.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/mrd-boolean-field2.js +1 -1
- package/dist/components/mrd-currency-field2.js +1 -1
- package/dist/components/mrd-date-field2.js +1 -1
- package/dist/components/mrd-datetime-field2.js +1 -1
- package/dist/components/mrd-document-container2.js +1 -1
- package/dist/components/mrd-document-list2.js +1 -1
- package/dist/components/mrd-document-view2.js +1 -1
- package/dist/components/mrd-email-field2.js +1 -1
- package/dist/components/mrd-email-view.d.ts +11 -0
- package/dist/components/mrd-email-view.js +1 -0
- package/dist/components/mrd-email-view2.js +1 -0
- package/dist/components/mrd-field2.js +1 -1
- package/dist/components/mrd-file-field2.js +1 -1
- package/dist/components/mrd-form.js +1 -1
- package/dist/components/mrd-image-field2.js +1 -1
- package/dist/components/mrd-invoice-view.d.ts +11 -0
- package/dist/components/mrd-invoice-view.js +1 -0
- package/dist/components/mrd-invoice-view2.js +1 -0
- package/dist/components/mrd-layout-section.js +1 -1
- package/dist/components/mrd-longtext-field2.js +1 -1
- package/dist/components/mrd-merge-view.js +1 -1
- package/dist/components/mrd-number-field2.js +1 -1
- package/dist/components/mrd-relation-field2.js +1 -1
- package/dist/components/mrd-secret-field2.js +1 -1
- package/dist/components/mrd-table2.js +1 -1
- package/dist/components/mrd-text-field2.js +1 -1
- package/dist/components/mrd-textarea-field2.js +1 -2
- package/dist/components/mrd-time-field2.js +1 -1
- package/dist/components/purify.es.js +2 -0
- package/dist/esm/{cell-renderer-D63AUZxa.js → cell-renderer-C2FLUrMN.js} +146 -2
- package/dist/esm/{client-layout-DCOAAH92.js → client-layout-Bc42CfJB.js} +7 -1
- package/dist/esm/{index-DiSe6vjv.js → index-CDiBvvJU.js} +468 -6
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/mosterdcomponents.js +3 -3
- package/dist/esm/{mrd-boolean-field_23.entry.js → mrd-boolean-field_25.entry.js} +5695 -5230
- package/dist/esm/mrd-merge-view.entry.js +5 -5
- package/dist/mosterdcomponents/index.esm.js +1 -1
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/{p-2e16a7d0.entry.js → p-4ea5b97c.entry.js} +1 -1
- package/dist/mosterdcomponents/p-8736313b.entry.js +3 -0
- package/dist/mosterdcomponents/{p-DCOAAH92.js → p-Bc42CfJB.js} +1 -1
- package/dist/mosterdcomponents/p-BgsPVesg.js +1 -0
- package/dist/mosterdcomponents/p-CDiBvvJU.js +2 -0
- package/dist/types/components/documents/mrd-document-container/mrd-document-container.d.ts +7 -0
- package/dist/types/components/documents/mrd-document-list/mrd-document-list.d.ts +17 -0
- package/dist/types/components/documents/mrd-document-view/mrd-document-view.d.ts +2 -2
- package/dist/types/components/email/mrd-email-view/mrd-email-view.d.ts +52 -0
- package/dist/types/components/fields/file-upload-common.d.ts +19 -1
- package/dist/types/components/fields/mrd-file-field/mrd-file-field.d.ts +24 -10
- package/dist/types/components/fields/mrd-image-field/mrd-image-field.d.ts +27 -11
- package/dist/types/components/fields/mrd-relation-field/mrd-relation-field.d.ts +7 -0
- package/dist/types/components/form/mrd-form/mrd-form.d.ts +19 -3
- package/dist/types/components/invoice/mrd-invoice-view/mrd-invoice-view.d.ts +60 -0
- package/dist/types/components/layout/mrd-layout-section/layout-helpers.d.ts +3 -0
- package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +13 -0
- package/dist/types/components.d.ts +303 -19
- package/dist/types/types/client-layout.d.ts +13 -0
- package/dist/types/utils/document-attachments.d.ts +12 -5
- package/package.json +1 -1
- package/dist/mosterdcomponents/p-CnqDM0Gb.js +0 -1
- package/dist/mosterdcomponents/p-DiSe6vjv.js +0 -2
- package/dist/mosterdcomponents/p-b5f38707.entry.js +0 -3
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
width: 100%;
|
|
90
90
|
}
|
|
91
91
|
.mrd-image-field__preview-thumb {
|
|
92
|
+
position: relative;
|
|
92
93
|
flex-shrink: 0;
|
|
93
94
|
width: 80px;
|
|
94
95
|
height: 80px;
|
|
@@ -159,6 +160,49 @@
|
|
|
159
160
|
background-color: var(--mrd-color-danger);
|
|
160
161
|
color: var(--mrd-color-white);
|
|
161
162
|
}
|
|
163
|
+
.mrd-image-field__grid {
|
|
164
|
+
list-style: none;
|
|
165
|
+
display: flex;
|
|
166
|
+
flex-wrap: wrap;
|
|
167
|
+
gap: var(--mrd-space-3);
|
|
168
|
+
margin: var(--mrd-space-2) 0 0;
|
|
169
|
+
padding: 0;
|
|
170
|
+
}
|
|
171
|
+
.mrd-image-field__grid-item {
|
|
172
|
+
position: relative;
|
|
173
|
+
display: flex;
|
|
174
|
+
flex-direction: column;
|
|
175
|
+
align-items: center;
|
|
176
|
+
gap: var(--mrd-space-1);
|
|
177
|
+
width: 88px;
|
|
178
|
+
}
|
|
179
|
+
.mrd-image-field__grid-name {
|
|
180
|
+
font-family: var(--mrd-font-family);
|
|
181
|
+
font-size: var(--mrd-font-size-xs);
|
|
182
|
+
color: var(--mrd-color-neutral-600);
|
|
183
|
+
max-width: 100%;
|
|
184
|
+
overflow: hidden;
|
|
185
|
+
text-overflow: ellipsis;
|
|
186
|
+
white-space: nowrap;
|
|
187
|
+
}
|
|
188
|
+
.mrd-image-field__grid-remove {
|
|
189
|
+
position: absolute;
|
|
190
|
+
top: -6px;
|
|
191
|
+
right: -6px;
|
|
192
|
+
width: 20px;
|
|
193
|
+
height: 20px;
|
|
194
|
+
line-height: 1;
|
|
195
|
+
background-color: var(--mrd-color-white);
|
|
196
|
+
color: var(--mrd-color-neutral-500);
|
|
197
|
+
border: var(--mrd-border-width) solid var(--mrd-border-color);
|
|
198
|
+
border-radius: 50%;
|
|
199
|
+
cursor: pointer;
|
|
200
|
+
font-size: var(--mrd-font-size-xs);
|
|
201
|
+
}
|
|
202
|
+
.mrd-image-field__grid-remove:hover {
|
|
203
|
+
color: var(--mrd-color-danger);
|
|
204
|
+
border-color: var(--mrd-color-danger);
|
|
205
|
+
}
|
|
162
206
|
|
|
163
207
|
@keyframes mrd-spin {
|
|
164
208
|
to {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Host, h } from "@stencil/core";
|
|
2
2
|
import { t } from "../../../utils/i18n";
|
|
3
3
|
import { FieldLabel, FieldError } from "../field-helpers";
|
|
4
|
-
import { validateUploadFile, uploadZoneClass, makeDragHandlers } from "../file-upload-common";
|
|
4
|
+
import { isPending, entryLabel, validateUploadFile, uploadZoneClass, makeDragHandlers } from "../file-upload-common";
|
|
5
5
|
export class MrdImageField {
|
|
6
6
|
constructor() {
|
|
7
7
|
this.name = '';
|
|
@@ -12,79 +12,125 @@ export class MrdImageField {
|
|
|
12
12
|
this.locale = navigator.language;
|
|
13
13
|
this.accept = 'image/*';
|
|
14
14
|
this.maxSize = 0;
|
|
15
|
-
this.
|
|
16
|
-
|
|
15
|
+
this.multiple = false;
|
|
16
|
+
/** Working copy of the field's files, kept in sync with `value`. Entries still
|
|
17
|
+
* a `File` are pending upload; resolved entries are `{ href, fileName }` (or a
|
|
18
|
+
* bare href string for older hosts). */
|
|
19
|
+
this.entries = [];
|
|
17
20
|
this.isDragging = false;
|
|
18
|
-
this.uploading = false;
|
|
19
21
|
this.error = '';
|
|
22
|
+
/** Local data-URL previews for pending File entries, keyed by File reference. */
|
|
23
|
+
this.previewCache = new Map();
|
|
20
24
|
this.handleInputChange = (e) => {
|
|
21
25
|
var _a;
|
|
22
|
-
const
|
|
23
|
-
this.
|
|
26
|
+
const input = e.target;
|
|
27
|
+
this.addFiles(Array.from((_a = input.files) !== null && _a !== void 0 ? _a : []));
|
|
28
|
+
input.value = '';
|
|
24
29
|
};
|
|
25
|
-
this.drag = makeDragHandlers(dragging => (this.isDragging = dragging),
|
|
30
|
+
this.drag = makeDragHandlers(dragging => (this.isDragging = dragging), files => this.addFiles(files));
|
|
26
31
|
this.handleZoneClick = () => {
|
|
27
32
|
var _a;
|
|
28
|
-
if (!this.disabled && !this.
|
|
33
|
+
if (!this.disabled && !this.zoneBusy) {
|
|
29
34
|
(_a = this.fileInputRef) === null || _a === void 0 ? void 0 : _a.click();
|
|
30
35
|
}
|
|
31
36
|
};
|
|
32
|
-
this.
|
|
37
|
+
this.handleRemove = (index) => (e) => {
|
|
33
38
|
e.stopPropagation();
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
const removed = this.entries[index];
|
|
40
|
+
if (removed instanceof File)
|
|
41
|
+
this.previewCache.delete(removed);
|
|
42
|
+
const next = this.entries.filter((_, i) => i !== index);
|
|
43
|
+
this.entries = next;
|
|
36
44
|
this.error = '';
|
|
37
|
-
this.uploading = false;
|
|
38
45
|
if (this.fileInputRef)
|
|
39
46
|
this.fileInputRef.value = '';
|
|
40
|
-
this.
|
|
47
|
+
this.emitValue(next);
|
|
41
48
|
};
|
|
42
49
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (typeof newVal === 'string' && newVal) {
|
|
46
|
-
this.uploading = false;
|
|
47
|
-
}
|
|
48
|
-
else if (!newVal) {
|
|
49
|
-
this.uploading = false;
|
|
50
|
-
this.previewUrl = '';
|
|
51
|
-
this.fileName = '';
|
|
52
|
-
}
|
|
50
|
+
componentWillLoad() {
|
|
51
|
+
this.syncEntriesFromValue();
|
|
53
52
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
/** The host (via mrd-form.setFieldValue) is the source of truth once a value round-trips back. */
|
|
54
|
+
valueChanged() {
|
|
55
|
+
this.syncEntriesFromValue();
|
|
56
|
+
}
|
|
57
|
+
syncEntriesFromValue() {
|
|
58
|
+
const v = this.value;
|
|
59
|
+
if (this.multiple) {
|
|
60
|
+
this.entries = Array.isArray(v) ? [...v] : v ? [v] : [];
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.error = uploadError;
|
|
65
|
-
return;
|
|
62
|
+
else {
|
|
63
|
+
this.entries = v ? [v] : [];
|
|
66
64
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
}
|
|
66
|
+
emitValue(entries) {
|
|
67
|
+
var _a;
|
|
68
|
+
const value = this.multiple ? entries : (_a = entries[0]) !== null && _a !== void 0 ? _a : null;
|
|
69
|
+
this.mrdChange.emit({ name: this.name, value: value });
|
|
70
|
+
}
|
|
71
|
+
readPreview(file) {
|
|
71
72
|
const reader = new FileReader();
|
|
72
|
-
reader.onload =
|
|
73
|
+
reader.onload = ev => {
|
|
73
74
|
var _a;
|
|
74
|
-
this.
|
|
75
|
+
this.previewCache.set(file, (_a = ev.target) === null || _a === void 0 ? void 0 : _a.result);
|
|
76
|
+
this.entries = [...this.entries]; // trigger re-render now that the preview is ready
|
|
75
77
|
};
|
|
76
78
|
reader.readAsDataURL(file);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
}
|
|
80
|
+
addFiles(files) {
|
|
81
|
+
if (this.disabled || this.zoneBusy)
|
|
82
|
+
return;
|
|
83
|
+
const candidates = this.multiple ? files : files.slice(0, 1);
|
|
84
|
+
if (!candidates.length)
|
|
85
|
+
return;
|
|
86
|
+
const accepted = [];
|
|
87
|
+
let uploadError = '';
|
|
88
|
+
for (const file of candidates) {
|
|
89
|
+
const err = validateUploadFile(file, this.maxSize, this.locale, true);
|
|
90
|
+
if (err) {
|
|
91
|
+
uploadError = err;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
accepted.push(file);
|
|
95
|
+
}
|
|
96
|
+
this.error = uploadError;
|
|
97
|
+
if (!accepted.length)
|
|
98
|
+
return;
|
|
99
|
+
const next = this.multiple ? [...this.entries, ...accepted] : [accepted[0]];
|
|
100
|
+
this.entries = next;
|
|
101
|
+
this.emitValue(next);
|
|
102
|
+
for (const file of accepted) {
|
|
103
|
+
this.readPreview(file);
|
|
104
|
+
this.mrdUpload.emit({ name: this.name, file });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** In single mode, block re-selection while the one image is still uploading;
|
|
108
|
+
* in multiple mode, more images can always be added alongside pending uploads. */
|
|
109
|
+
get zoneBusy() {
|
|
110
|
+
return !this.multiple && this.entries.some(isPending);
|
|
111
|
+
}
|
|
112
|
+
renderThumb(entry) {
|
|
113
|
+
const uploading = isPending(entry);
|
|
114
|
+
const previewUrl = uploading ? this.previewCache.get(entry) : null;
|
|
115
|
+
return (h("div", { class: "mrd-image-field__preview-thumb" }, previewUrl && h("img", { class: "mrd-image-field__preview", src: previewUrl, alt: entryLabel(entry) }), uploading && (h("div", { class: "mrd-image-field__preview-overlay" }, h("span", { class: "mrd-image-field__spinner", "aria-label": t('loading', this.locale) })))));
|
|
116
|
+
}
|
|
117
|
+
renderSingle(entry) {
|
|
118
|
+
const uploading = isPending(entry);
|
|
119
|
+
return (h("div", { class: "mrd-image-field__preview-container" }, this.renderThumb(entry), h("div", { class: "mrd-image-field__preview-info" }, h("span", { class: "mrd-image-field__preview-name" }, entryLabel(entry)), uploading && h("span", { class: "mrd-image-field__upload-status" }, t('loading', this.locale))), !uploading && (h("button", { class: "mrd-image-field__clear", type: "button", onClick: this.handleRemove(0), "aria-label": t('remove', this.locale) }, t('remove', this.locale)))));
|
|
120
|
+
}
|
|
121
|
+
renderGridItem(entry, index) {
|
|
122
|
+
const uploading = isPending(entry);
|
|
123
|
+
return (h("li", { class: "mrd-image-field__grid-item", key: `${index}-${entryLabel(entry)}` }, this.renderThumb(entry), h("span", { class: "mrd-image-field__grid-name" }, entryLabel(entry)), !uploading && (h("button", { class: "mrd-image-field__grid-remove", type: "button", onClick: this.handleRemove(index), "aria-label": t('remove', this.locale) }, "\u2715"))));
|
|
79
124
|
}
|
|
80
125
|
render() {
|
|
81
126
|
const hasError = !!this.error;
|
|
127
|
+
const hasEntries = this.entries.length > 0;
|
|
82
128
|
const zoneClass = uploadZoneClass('mrd-image-field', {
|
|
83
129
|
dragging: this.isDragging,
|
|
84
130
|
error: hasError,
|
|
85
|
-
disabled: this.disabled || this.
|
|
131
|
+
disabled: this.disabled || this.zoneBusy,
|
|
86
132
|
});
|
|
87
|
-
return (h(Host, { key: '
|
|
133
|
+
return (h(Host, { key: '51d39ea80195565a5dc780ff6a7923a976cfb0a7' }, h("div", { key: 'd76edb7ac9f1efea8c7c3d5b04e906ad4ab4c761', class: "mrd-image-field" }, h(FieldLabel, { key: 'b46a67a76188047677c40ce3f406daed7d8de141', base: "mrd-image-field", label: this.label, required: this.required }), h("div", { key: '0156a9722ea48d84e3ea1a829e4266425a594a6a', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.drag.onDragOver, onDragLeave: this.drag.onDragLeave, onDrop: this.drag.onDrop }, h("input", { key: '1b8e41da71bb57254bfd2e5527b05e1aeb32eb2f', ref: el => (this.fileInputRef = el), class: "mrd-image-field__input", type: "file", name: this.name, accept: this.accept, multiple: this.multiple, disabled: this.disabled || this.zoneBusy, required: this.required && !hasEntries, onChange: this.handleInputChange }), hasEntries && !this.multiple ? (this.renderSingle(this.entries[0])) : (h("div", { class: "mrd-image-field__prompt" }, h("svg", { class: "mrd-image-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }), h("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), h("polyline", { points: "21 15 16 10 5 21" })), h("span", null, t('drop_file_here', this.locale), ' ', h("span", { class: "mrd-image-field__browse" }, t('browse', this.locale)))))), this.multiple && hasEntries && (h("ul", { key: '9211b5212eae0629f7c9b2b49d80e2b658a9ddd3', class: "mrd-image-field__grid" }, this.entries.map((entry, index) => this.renderGridItem(entry, index)))), h(FieldError, { key: '5f49c03156ed18e7c8307adff679b149658ca4a6', base: "mrd-image-field", error: this.error }))));
|
|
88
134
|
}
|
|
89
135
|
static get is() { return "mrd-image-field"; }
|
|
90
136
|
static get encapsulation() { return "scoped"; }
|
|
@@ -257,15 +303,33 @@ export class MrdImageField {
|
|
|
257
303
|
"reflect": false,
|
|
258
304
|
"attribute": "max-size",
|
|
259
305
|
"defaultValue": "0"
|
|
306
|
+
},
|
|
307
|
+
"multiple": {
|
|
308
|
+
"type": "boolean",
|
|
309
|
+
"mutable": false,
|
|
310
|
+
"complexType": {
|
|
311
|
+
"original": "boolean",
|
|
312
|
+
"resolved": "boolean",
|
|
313
|
+
"references": {}
|
|
314
|
+
},
|
|
315
|
+
"required": false,
|
|
316
|
+
"optional": false,
|
|
317
|
+
"docs": {
|
|
318
|
+
"tags": [],
|
|
319
|
+
"text": ""
|
|
320
|
+
},
|
|
321
|
+
"getter": false,
|
|
322
|
+
"setter": false,
|
|
323
|
+
"reflect": false,
|
|
324
|
+
"attribute": "multiple",
|
|
325
|
+
"defaultValue": "false"
|
|
260
326
|
}
|
|
261
327
|
};
|
|
262
328
|
}
|
|
263
329
|
static get states() {
|
|
264
330
|
return {
|
|
265
|
-
"
|
|
266
|
-
"fileName": {},
|
|
331
|
+
"entries": {},
|
|
267
332
|
"isDragging": {},
|
|
268
|
-
"uploading": {},
|
|
269
333
|
"error": {}
|
|
270
334
|
};
|
|
271
335
|
}
|
|
@@ -281,12 +345,14 @@ export class MrdImageField {
|
|
|
281
345
|
"text": ""
|
|
282
346
|
},
|
|
283
347
|
"complexType": {
|
|
284
|
-
"original": "{ name: string; value:
|
|
285
|
-
"resolved": "{ name: string; value:
|
|
348
|
+
"original": "{ name: string; value: FileEntry | FileEntry[] | null }",
|
|
349
|
+
"resolved": "{ name: string; value: FileEntry | FileEntry[] | null; }",
|
|
286
350
|
"references": {
|
|
287
|
-
"
|
|
288
|
-
"location": "
|
|
289
|
-
"
|
|
351
|
+
"FileEntry": {
|
|
352
|
+
"location": "import",
|
|
353
|
+
"path": "../file-upload-common",
|
|
354
|
+
"id": "src/components/fields/file-upload-common.ts::FileEntry",
|
|
355
|
+
"referenceLocation": "FileEntry"
|
|
290
356
|
}
|
|
291
357
|
}
|
|
292
358
|
}
|
|
@@ -301,12 +367,14 @@ export class MrdImageField {
|
|
|
301
367
|
"text": ""
|
|
302
368
|
},
|
|
303
369
|
"complexType": {
|
|
304
|
-
"original": "{ name: string; value:
|
|
305
|
-
"resolved": "{ name: string; value:
|
|
370
|
+
"original": "{ name: string; value: FileEntry | FileEntry[] | null }",
|
|
371
|
+
"resolved": "{ name: string; value: FileEntry | FileEntry[] | null; }",
|
|
306
372
|
"references": {
|
|
307
|
-
"
|
|
308
|
-
"location": "
|
|
309
|
-
"
|
|
373
|
+
"FileEntry": {
|
|
374
|
+
"location": "import",
|
|
375
|
+
"path": "../file-upload-common",
|
|
376
|
+
"id": "src/components/fields/file-upload-common.ts::FileEntry",
|
|
377
|
+
"referenceLocation": "FileEntry"
|
|
310
378
|
}
|
|
311
379
|
}
|
|
312
380
|
}
|
|
@@ -318,7 +386,7 @@ export class MrdImageField {
|
|
|
318
386
|
"composed": true,
|
|
319
387
|
"docs": {
|
|
320
388
|
"tags": [],
|
|
321
|
-
"text": "Emitted
|
|
389
|
+
"text": "Emitted once per selected/dropped image that needs to be uploaded.\nHost should upload the file and call form.setFieldValue(name, { href, fileName: file.name }, file)\nwith the result \u2014 passing `file` back lets mrd-form resolve the right entry in a `multiple` field."
|
|
322
390
|
},
|
|
323
391
|
"complexType": {
|
|
324
392
|
"original": "{ name: string; file: File }",
|
|
@@ -21,7 +21,7 @@ export class MrdLongtextField {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
render() {
|
|
24
|
-
return (h(Host, { key: '
|
|
24
|
+
return (h(Host, { key: 'e53fec4d4eafbd68d9cffb1f064d8e0c4c37839c' }, h("div", { key: '8843a23e42b0545c269fc6c924e7ae295770064e', class: "mrd-longtext-field" }, h(FieldLabel, { key: '8767676dd35f25f9bf5ebdb26887edc0882582e0', base: "mrd-longtext-field", label: this.label, required: this.required }), this.disabled ? (h("pre", { class: "mrd-longtext-field__content" }, this.value)) : (h("textarea", { class: controlClass('mrd-longtext-field', !!this.error), name: this.name, placeholder: this.placeholder, required: this.required, rows: 10, onInput: this.handleInput, onBlur: this.handleBlur }, this.value)), h(FieldError, { key: '54dc790173575e8a02764e5b14040b900c2eb609', base: "mrd-longtext-field", error: this.error }))));
|
|
25
25
|
}
|
|
26
26
|
static get is() { return "mrd-longtext-field"; }
|
|
27
27
|
static get encapsulation() { return "scoped"; }
|
|
@@ -70,7 +70,7 @@ export class MrdNumberField {
|
|
|
70
70
|
const hasError = !!this.error;
|
|
71
71
|
const suffix = this.dataType === ClientLayoutItemFieldDataType.PERCENTAGE ? '%' :
|
|
72
72
|
this.dataType === ClientLayoutItemFieldDataType.DECIMAL ? '' : '';
|
|
73
|
-
return (h(Host, { key: '
|
|
73
|
+
return (h(Host, { key: '5df5c2e16c85cd54944d95b7a8c340ae1a4ddb34' }, h("div", { key: 'e332bd0190d537c002b14090fa96ec6502e34746', class: "mrd-number-field" }, h(FieldLabel, { key: 'e26ae85ef6c6d7935b2d34041a7ee2294da392a4', base: "mrd-number-field", label: this.label, required: this.required }), h("div", { key: 'fb1a44a363a36b69124a0092e80b67d41b538c03', class: "mrd-number-field__input-wrapper" }, h("input", { key: '175c448177bbd46015fc7f47b98b76e16ee3b743', class: controlClass('mrd-number-field', hasError), type: "text", inputMode: "decimal", name: this.name, value: this.displayValue, placeholder: this.placeholder || (suffix ? `0${suffix}` : '0'), required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur, onFocus: this.handleFocus })), h(FieldError, { key: 'ecb16ddf655e563f0569e774ab2f2e419f60b0f1', base: "mrd-number-field", error: this.error }))));
|
|
74
74
|
}
|
|
75
75
|
static get is() { return "mrd-number-field"; }
|
|
76
76
|
static get encapsulation() { return "scoped"; }
|
|
@@ -121,16 +121,22 @@ export class MrdRelationField {
|
|
|
121
121
|
async setAllRecords(records) {
|
|
122
122
|
this.allRecords = records;
|
|
123
123
|
}
|
|
124
|
+
/** Href of the current single value. Accepts both a RelationSearchResult
|
|
125
|
+
* (`id`) and the raw API link shape (`{ href, name }`) a host puts in the
|
|
126
|
+
* form values for edit mode — same tolerance as `toSearchResult()`. */
|
|
124
127
|
getValueHref() {
|
|
125
|
-
var _a, _b, _c;
|
|
128
|
+
var _a, _b, _c, _d;
|
|
126
129
|
const v = Array.isArray(this.value) ? ((_a = this.value[0]) !== null && _a !== void 0 ? _a : '') : ((_b = this.value) !== null && _b !== void 0 ? _b : '');
|
|
127
130
|
if (!v)
|
|
128
131
|
return '';
|
|
129
132
|
if (typeof v === 'object')
|
|
130
|
-
return (_c = v.id) !== null && _c !== void 0 ? _c : '';
|
|
133
|
+
return (_d = (_c = v.id) !== null && _c !== void 0 ? _c : v.href) !== null && _d !== void 0 ? _d : '';
|
|
131
134
|
return v;
|
|
132
135
|
}
|
|
133
|
-
|
|
136
|
+
/** Push the current value onto the rendered <select>. Options and value arrive
|
|
137
|
+
* independently in edit mode (fetched records vs. the async `values` prop), so
|
|
138
|
+
* this runs on both — whichever lands last completes the preselection. */
|
|
139
|
+
syncDropdownSelection() {
|
|
134
140
|
if (this.editBehavior !== ClientLayoutItemRelationEditBehavior.DROPDOWN)
|
|
135
141
|
return;
|
|
136
142
|
const current = this.getValueHref();
|
|
@@ -146,6 +152,9 @@ export class MrdRelationField {
|
|
|
146
152
|
select.value = current;
|
|
147
153
|
}, 0);
|
|
148
154
|
}
|
|
155
|
+
allRecordsChanged() {
|
|
156
|
+
this.syncDropdownSelection();
|
|
157
|
+
}
|
|
149
158
|
async setSearchResults(results) {
|
|
150
159
|
this.searchResults = results;
|
|
151
160
|
this.isLoading = false;
|
|
@@ -197,6 +206,7 @@ export class MrdRelationField {
|
|
|
197
206
|
// (host pre-fill). Plain href strings from user interaction are ignored.
|
|
198
207
|
valueChanged(newValue) {
|
|
199
208
|
this.applyValuePrefill(newValue);
|
|
209
|
+
this.syncDropdownSelection();
|
|
200
210
|
}
|
|
201
211
|
componentDidLoad() {
|
|
202
212
|
// Only emit when there is no commonRelation dependency — the form orchestrates those.
|
|
@@ -21,9 +21,9 @@ export class MrdSecretField {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
render() {
|
|
24
|
-
return (h(Host, { key: '
|
|
24
|
+
return (h(Host, { key: 'e06d04fdae34b42441976e21605fe94ad935382e' }, h("div", { key: '2889e1eb1b6d0887ae531523a0b9b43c49ef6f99', class: "mrd-secret-field" }, h(FieldLabel, { key: 'c40907905292cdef8bb0b8b9b0c03e05650bef37', base: "mrd-secret-field", label: this.label, required: this.required }), this.disabled
|
|
25
25
|
? (h("span", { class: "mrd-secret-field__masked", "aria-label": this.label }, this.value ? '••••••••' : ''))
|
|
26
|
-
: (h("input", { class: controlClass('mrd-secret-field', !!this.error), type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), h(FieldError, { key: '
|
|
26
|
+
: (h("input", { class: controlClass('mrd-secret-field', !!this.error), type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), h(FieldError, { key: '6353e4b40566852dbc1994c7c9c409d0d0aa1b37', base: "mrd-secret-field", error: this.error }))));
|
|
27
27
|
}
|
|
28
28
|
static get is() { return "mrd-secret-field"; }
|
|
29
29
|
static get encapsulation() { return "scoped"; }
|
|
@@ -21,7 +21,7 @@ export class MrdTextField {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
render() {
|
|
24
|
-
return (h(Host, { key: '
|
|
24
|
+
return (h(Host, { key: '3153f0c6f8ab4d9dae93306f7507399aeda75eaf' }, h("div", { key: '5d9c28023fdfb5472fc115c66bc3df509506e10f', class: "mrd-text-field" }, h(FieldLabel, { key: '1e21139aae0cc1ae95aa3297271b618a40043e77', base: "mrd-text-field", label: this.label, required: this.required }), h("input", { key: '46f98d5e39bb834075449fac7096b077a1ae7bb3', class: controlClass('mrd-text-field', !!this.error), type: "text", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), h(FieldError, { key: '10b6ddae9cd9f36dc9d7176167d79df8e4102c03', base: "mrd-text-field", error: this.error }))));
|
|
25
25
|
}
|
|
26
26
|
static get is() { return "mrd-text-field"; }
|
|
27
27
|
static get encapsulation() { return "scoped"; }
|
|
@@ -64,7 +64,7 @@ export class MrdTextareaField {
|
|
|
64
64
|
return DOMPurify.sanitize(html);
|
|
65
65
|
}
|
|
66
66
|
render() {
|
|
67
|
-
return (h(Host, { key: '
|
|
67
|
+
return (h(Host, { key: 'e132531881f68f373e700617aac8033c8ebccb47' }, h("div", { key: 'fec0cf56cd7868d3fcd5a4e8a382b2dcdb6e5c50', class: "mrd-textarea-field" }, h(FieldLabel, { key: '333aa2ff57cce9e3178f0c4be4a1df1077884248', base: "mrd-textarea-field", label: this.label, required: this.required }), h("div", { key: '40025207580eb5768981b85aaa0a8ff95fce7234', class: controlClass('mrd-textarea-field', !!this.error, 'container') }, h("div", { key: '621987b3b2b1d8b4836bff065075ba527a82db81', class: "mrd-textarea-field__editor" })), h(FieldError, { key: 'ac2d8de22f008cd1c91842137ccd0cd36eb9ce19', base: "mrd-textarea-field", error: this.error }))));
|
|
68
68
|
}
|
|
69
69
|
static get is() { return "mrd-textarea-field"; }
|
|
70
70
|
static get encapsulation() { return "scoped"; }
|
|
@@ -20,7 +20,7 @@ export class MrdTimeField {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
render() {
|
|
23
|
-
return (h(Host, { key: '
|
|
23
|
+
return (h(Host, { key: 'd521c654bc7beda71a31542a25198edaaf53b838' }, h("div", { key: '084ab16ac8aed952bd0ec50e0430591d4db5bd4b', class: "mrd-time-field" }, h(FieldLabel, { key: '43938ad7c5a9765353f6523d399d4b74cbb9ec6f', base: "mrd-time-field", label: this.label, required: this.required }), h("input", { key: 'e46eda620e7a5f1bb3b433a4c051e913675c33f9', class: controlClass('mrd-time-field', !!this.error), type: "time", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), h(FieldError, { key: '34bc1eaa1b969951dffaaacad73af532b6d290fb', base: "mrd-time-field", error: this.error }))));
|
|
24
24
|
}
|
|
25
25
|
static get is() { return "mrd-time-field"; }
|
|
26
26
|
static get encapsulation() { return "scoped"; }
|
|
@@ -111,7 +111,7 @@ export class MrdField {
|
|
|
111
111
|
return (h("div", { class: "mrd-field__history-editor" }, this.historyEntries.length > 0 && (h("span", { class: "mrd-field__history-editor-label" }, t('history_badge_tooltip', locale))), this.historyEntries.map((entry, i) => (h("div", { key: String(i), class: "mrd-field__history-editor-row" }, h("input", { class: "mrd-field__history-editor-value", type: valueType, value: entry.value, onInput: (e) => updateEntry(i, 'value', e.target.value) }), h("span", { class: "mrd-field__history-editor-sep" }, t('history_until', locale)), h("input", { class: "mrd-field__history-editor-until", type: "date", value: entry.until, onInput: (e) => updateEntry(i, 'until', e.target.value) }), h("button", { type: "button", class: "mrd-field__history-editor-remove", onClick: () => removeEntry(i), "aria-label": t('remove', locale) }, h("svg", { viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true" }, h("path", { "fill-rule": "evenodd", d: "M8.75 1A2.75 2.75 0 006 3.75v.443c-.795.077-1.584.176-2.365.298a.75.75 0 10.23 1.482l.149-.022.841 10.518A2.75 2.75 0 007.596 19h4.807a2.75 2.75 0 002.742-2.53l.841-10.52.149.023a.75.75 0 00.23-1.482A41.03 41.03 0 0014 4.193V3.75A2.75 2.75 0 0011.25 1h-2.5zM10 4c.84 0 1.673.025 2.5.075V3.75c0-.69-.56-1.25-1.25-1.25h-2.5c-.69 0-1.25.56-1.25 1.25v.325C8.327 4.025 9.16 4 10 4zM8.58 7.72a.75.75 0 00-1.5.06l.3 7.5a.75.75 0 101.5-.06l-.3-7.5zm4.34.06a.75.75 0 10-1.5-.06l-.3 7.5a.75.75 0 101.5.06l.3-7.5z", "clip-rule": "evenodd" })))))), h("button", { type: "button", class: "mrd-field__history-editor-add", onClick: addEntry }, "+ ", t('add', locale))));
|
|
112
112
|
}
|
|
113
113
|
renderLeafField(displayValue) {
|
|
114
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
|
|
114
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
|
|
115
115
|
const { item, locale } = this;
|
|
116
116
|
const commonProps = {
|
|
117
117
|
name: item.name,
|
|
@@ -148,13 +148,13 @@ export class MrdField {
|
|
|
148
148
|
case ClientLayoutItemFieldDataType.LIST:
|
|
149
149
|
return (h("mrd-list-field", Object.assign({}, commonProps, { value: (_u = displayValue) !== null && _u !== void 0 ? _u : '', multiple: (_v = item.multiple) !== null && _v !== void 0 ? _v : false, listItems: (_w = item.listItems) !== null && _w !== void 0 ? _w : [] })));
|
|
150
150
|
case ClientLayoutItemFieldDataType.FILE:
|
|
151
|
-
return (h("mrd-file-field", Object.assign({}, commonProps, { value: displayValue, accept: (_x = item.accept) !== null && _x !== void 0 ? _x : '', maxSize: (_y = item.maxSize) !== null && _y !== void 0 ? _y : 0, onMrdUpload: this.handleUpload })));
|
|
151
|
+
return (h("mrd-file-field", Object.assign({}, commonProps, { value: displayValue, accept: (_x = item.accept) !== null && _x !== void 0 ? _x : '', maxSize: (_y = item.maxSize) !== null && _y !== void 0 ? _y : 0, multiple: (_z = item.multiple) !== null && _z !== void 0 ? _z : false, onMrdUpload: this.handleUpload })));
|
|
152
152
|
case ClientLayoutItemFieldDataType.IMAGE:
|
|
153
|
-
return (h("mrd-image-field", Object.assign({}, commonProps, { value: displayValue, accept: (
|
|
153
|
+
return (h("mrd-image-field", Object.assign({}, commonProps, { value: displayValue, accept: (_0 = item.accept) !== null && _0 !== void 0 ? _0 : 'image/*', maxSize: (_1 = item.maxSize) !== null && _1 !== void 0 ? _1 : 0, multiple: (_2 = item.multiple) !== null && _2 !== void 0 ? _2 : false, onMrdUpload: this.handleUpload })));
|
|
154
154
|
case ClientLayoutItemFieldDataType.LONGTEXT:
|
|
155
|
-
return (h("mrd-longtext-field", Object.assign({}, commonProps, { value: (
|
|
155
|
+
return (h("mrd-longtext-field", Object.assign({}, commonProps, { value: (_3 = displayValue) !== null && _3 !== void 0 ? _3 : '', placeholder: (_4 = item.placeholder) !== null && _4 !== void 0 ? _4 : '' })));
|
|
156
156
|
case ClientLayoutItemFieldDataType.SECRET:
|
|
157
|
-
return (h("mrd-secret-field", Object.assign({}, commonProps, { value: (
|
|
157
|
+
return (h("mrd-secret-field", Object.assign({}, commonProps, { value: (_5 = displayValue) !== null && _5 !== void 0 ? _5 : '', placeholder: (_6 = item.placeholder) !== null && _6 !== void 0 ? _6 : '' })));
|
|
158
158
|
default:
|
|
159
159
|
return null;
|
|
160
160
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Host, h } from "@stencil/core";
|
|
2
|
-
import { ClientLayoutItemType, ClientLayoutItemRelationEditBehavior } from "../../../types";
|
|
2
|
+
import { ClientLayoutItemFieldDataType, ClientLayoutItemType, ClientLayoutItemRelationEditBehavior } from "../../../types";
|
|
3
3
|
import { t } from "../../../utils/i18n";
|
|
4
4
|
import { validateRequired } from "../../../utils/validation";
|
|
5
5
|
export class MrdForm {
|
|
@@ -199,7 +199,31 @@ export class MrdForm {
|
|
|
199
199
|
}
|
|
200
200
|
return null;
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Inject a value from outside (e.g. after a file upload completes).
|
|
204
|
+
* `file` is optional and only meaningful for `multiple` FILE/IMAGE fields: when
|
|
205
|
+
* the field's current value is an array, mrd-form replaces the array entry that
|
|
206
|
+
* `=== file` with `value`, leaving other pending/resolved entries untouched —
|
|
207
|
+
* this is how mrd-file-field/mrd-image-field resolve concurrent per-file uploads.
|
|
208
|
+
* Pass the `file` from the originating mrdUpload event back unchanged.
|
|
209
|
+
*/
|
|
210
|
+
async setFieldValue(name, value, file) {
|
|
211
|
+
if (file) {
|
|
212
|
+
const current = this.formValues[name];
|
|
213
|
+
if (Array.isArray(current)) {
|
|
214
|
+
const index = current.indexOf(file);
|
|
215
|
+
if (index === -1)
|
|
216
|
+
return; // the file was removed from the field before its upload resolved
|
|
217
|
+
const next = [...current];
|
|
218
|
+
next[index] = value;
|
|
219
|
+
this.formValues = Object.assign(Object.assign({}, this.formValues), { [name]: next });
|
|
220
|
+
if (this.errors[name])
|
|
221
|
+
this.errors = Object.assign(Object.assign({}, this.errors), { [name]: '' });
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (current !== file)
|
|
225
|
+
return; // stale resolution for a value that was since cleared/replaced
|
|
226
|
+
}
|
|
203
227
|
this.formValues = Object.assign(Object.assign({}, this.formValues), { [name]: value });
|
|
204
228
|
if (this.errors[name]) {
|
|
205
229
|
this.errors = Object.assign(Object.assign({}, this.errors), { [name]: '' });
|
|
@@ -229,15 +253,19 @@ export class MrdForm {
|
|
|
229
253
|
}
|
|
230
254
|
}
|
|
231
255
|
}
|
|
232
|
-
/** Extract a plain href string from a form value
|
|
233
|
-
*
|
|
256
|
+
/** Extract a plain href string from a form value: a string, a
|
|
257
|
+
* RelationSearchResult-like object (`id`), or the raw API link shape
|
|
258
|
+
* (`{ href, name }`) hosts spread into `values` for edit mode. */
|
|
234
259
|
getHref(value) {
|
|
260
|
+
var _a, _b;
|
|
235
261
|
if (!value)
|
|
236
262
|
return '';
|
|
237
263
|
if (typeof value === 'string')
|
|
238
264
|
return value;
|
|
239
|
-
if (typeof value === 'object'
|
|
240
|
-
|
|
265
|
+
if (typeof value === 'object') {
|
|
266
|
+
const v = value;
|
|
267
|
+
return (_b = (_a = v.id) !== null && _a !== void 0 ? _a : v.href) !== null && _b !== void 0 ? _b : '';
|
|
268
|
+
}
|
|
241
269
|
return '';
|
|
242
270
|
}
|
|
243
271
|
collectFields(items) {
|
|
@@ -269,6 +297,20 @@ export class MrdForm {
|
|
|
269
297
|
normalizeFieldValue(value) {
|
|
270
298
|
return (value === '' || value == null) ? null : value;
|
|
271
299
|
}
|
|
300
|
+
/** FILE/IMAGE entries render as `{ href, fileName, contentType?, size? }` — the same
|
|
301
|
+
* shape the API returns for an already-persisted file — or a bare href string for
|
|
302
|
+
* freshly-resolved uploads. Only `href` is meaningful to the API, so unwrap before
|
|
303
|
+
* submit (mirrors normalizeRelationValue). Do NOT fall back to any other key (e.g.
|
|
304
|
+
* `id`) as a stand-in for `href` — a bare id is not a valid/complete reference on its
|
|
305
|
+
* own; if `href` is ever missing that's an API bug to fix upstream, not to paper over here. */
|
|
306
|
+
normalizeFileFieldValue(value) {
|
|
307
|
+
const toHref = (v) => v && typeof v === 'object' && 'href' in v ? v.href : v;
|
|
308
|
+
if (Array.isArray(value)) {
|
|
309
|
+
const hrefs = value.map(toHref).filter(v => v != null && v !== '');
|
|
310
|
+
return hrefs.length ? hrefs : null;
|
|
311
|
+
}
|
|
312
|
+
return this.normalizeFieldValue(toHref(value));
|
|
313
|
+
}
|
|
272
314
|
normalizeRelationValue(value) {
|
|
273
315
|
if (value == null || value === '')
|
|
274
316
|
return null;
|
|
@@ -315,8 +357,11 @@ export class MrdForm {
|
|
|
315
357
|
const rawValue = this.formValues[name];
|
|
316
358
|
if (rawValue instanceof File)
|
|
317
359
|
continue;
|
|
318
|
-
|
|
319
|
-
|
|
360
|
+
if (Array.isArray(rawValue) && rawValue.some(v => v instanceof File))
|
|
361
|
+
continue;
|
|
362
|
+
const isFileField = item.dataType === ClientLayoutItemFieldDataType.FILE || item.dataType === ClientLayoutItemFieldDataType.IMAGE;
|
|
363
|
+
const current = isFileField ? this.normalizeFileFieldValue(rawValue) : this.normalizeFieldValue(rawValue);
|
|
364
|
+
const initial = isFileField ? this.normalizeFileFieldValue(this.initialValues[name]) : this.normalizeFieldValue(this.initialValues[name]);
|
|
320
365
|
if (this.deepEqual(current, initial))
|
|
321
366
|
continue;
|
|
322
367
|
payload[name] = current;
|
|
@@ -619,7 +664,7 @@ export class MrdForm {
|
|
|
619
664
|
return {
|
|
620
665
|
"setFieldValue": {
|
|
621
666
|
"complexType": {
|
|
622
|
-
"signature": "(name: string, value: unknown) => Promise<void>",
|
|
667
|
+
"signature": "(name: string, value: unknown, file?: File) => Promise<void>",
|
|
623
668
|
"parameters": [{
|
|
624
669
|
"name": "name",
|
|
625
670
|
"type": "string",
|
|
@@ -628,17 +673,25 @@ export class MrdForm {
|
|
|
628
673
|
"name": "value",
|
|
629
674
|
"type": "unknown",
|
|
630
675
|
"docs": ""
|
|
676
|
+
}, {
|
|
677
|
+
"name": "file",
|
|
678
|
+
"type": "File | undefined",
|
|
679
|
+
"docs": ""
|
|
631
680
|
}],
|
|
632
681
|
"references": {
|
|
633
682
|
"Promise": {
|
|
634
683
|
"location": "global",
|
|
635
684
|
"id": "global::Promise"
|
|
685
|
+
},
|
|
686
|
+
"File": {
|
|
687
|
+
"location": "global",
|
|
688
|
+
"id": "global::File"
|
|
636
689
|
}
|
|
637
690
|
},
|
|
638
691
|
"return": "Promise<void>"
|
|
639
692
|
},
|
|
640
693
|
"docs": {
|
|
641
|
-
"text": "",
|
|
694
|
+
"text": "Inject a value from outside (e.g. after a file upload completes).\n`file` is optional and only meaningful for `multiple` FILE/IMAGE fields: when\nthe field's current value is an array, mrd-form replaces the array entry that\n`=== file` with `value`, leaving other pending/resolved entries untouched \u2014\nthis is how mrd-file-field/mrd-image-field resolve concurrent per-file uploads.\nPass the `file` from the originating mrdUpload event back unchanged.",
|
|
642
695
|
"tags": []
|
|
643
696
|
}
|
|
644
697
|
}
|