@windwalker-io/unicorn-next 0.1.18 → 0.1.21
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/chunks/_arrayPush.js +325 -108
- package/dist/chunks/_arrayPush.js.map +1 -1
- package/dist/chunks/_baseRest.js +155 -60
- package/dist/chunks/_baseRest.js.map +1 -1
- package/dist/chunks/_baseUnary.js +463 -0
- package/dist/chunks/_baseUnary.js.map +1 -0
- package/dist/chunks/_getPrototype.js +292 -100
- package/dist/chunks/_getPrototype.js.map +1 -1
- package/dist/chunks/alert-adapter.js +29 -0
- package/dist/chunks/alert-adapter.js.map +1 -0
- package/dist/chunks/alert.js +21 -0
- package/dist/chunks/alert.js.map +1 -0
- package/dist/chunks/arr.js +24 -0
- package/dist/chunks/arr.js.map +1 -0
- package/dist/chunks/button-radio.js +127 -145
- package/dist/chunks/button-radio.js.map +1 -1
- package/dist/chunks/checkboxes-multi-select.js +44 -43
- package/dist/chunks/checkboxes-multi-select.js.map +1 -1
- package/dist/chunks/chunk.js +24 -0
- package/dist/chunks/cloneDeep.js +679 -212
- package/dist/chunks/cloneDeep.js.map +1 -1
- package/dist/chunks/cropper.min.js +6 -5
- package/dist/chunks/cropper.min.js.map +1 -1
- package/dist/chunks/crypto.js +26 -0
- package/dist/chunks/crypto.js.map +1 -0
- package/dist/chunks/data.js +49 -0
- package/dist/chunks/data.js.map +1 -0
- package/dist/chunks/dom.js +128 -0
- package/dist/chunks/dom.js.map +1 -0
- package/dist/chunks/events.js +270 -0
- package/dist/chunks/events.js.map +1 -0
- package/dist/chunks/field-cascade-select.js +207 -250
- package/dist/chunks/field-cascade-select.js.map +1 -1
- package/dist/chunks/field-file-drag.js +175 -209
- package/dist/chunks/field-file-drag.js.map +1 -1
- package/dist/chunks/field-flatpickr.js +94 -898
- package/dist/chunks/field-flatpickr.js.map +1 -1
- package/dist/chunks/field-modal-select.js +728 -467
- package/dist/chunks/field-modal-select.js.map +1 -1
- package/dist/chunks/field-modal-tree.js +771 -766
- package/dist/chunks/field-modal-tree.js.map +1 -1
- package/dist/chunks/field-multi-uploader.js +249 -256
- package/dist/chunks/field-multi-uploader.js.map +1 -1
- package/dist/chunks/field-repeatable.js +111 -127
- package/dist/chunks/field-repeatable.js.map +1 -1
- package/dist/chunks/field-single-image-drag.js +286 -338
- package/dist/chunks/field-single-image-drag.js.map +1 -1
- package/dist/chunks/form.js +146 -159
- package/dist/chunks/form.js.map +1 -1
- package/dist/chunks/grid.js +349 -418
- package/dist/chunks/grid.js.map +1 -1
- package/dist/chunks/helper.js +39 -0
- package/dist/chunks/helper.js.map +1 -0
- package/dist/chunks/http-client.js +221 -211
- package/dist/chunks/http-client.js.map +1 -1
- package/dist/chunks/iframe-modal.js +95 -115
- package/dist/chunks/iframe-modal.js.map +1 -1
- package/dist/chunks/keep-tab.js +92 -101
- package/dist/chunks/keep-tab.js.map +1 -1
- package/dist/chunks/lang.js +250 -0
- package/dist/chunks/lang.js.map +1 -0
- package/dist/chunks/legacy.js +197 -201
- package/dist/chunks/legacy.js.map +1 -1
- package/dist/chunks/list-dependent.js +195 -228
- package/dist/chunks/list-dependent.js.map +1 -1
- package/dist/chunks/loader.js +106 -0
- package/dist/chunks/loader.js.map +1 -0
- package/dist/chunks/monthSelect.js +251 -0
- package/dist/chunks/monthSelect.js.map +1 -0
- package/dist/chunks/router.js +111 -0
- package/dist/chunks/router.js.map +1 -0
- package/dist/chunks/s3-multipart-uploader.js +183 -210
- package/dist/chunks/s3-multipart-uploader.js.map +1 -1
- package/dist/chunks/s3-uploader.js +106 -128
- package/dist/chunks/s3-uploader.js.map +1 -1
- package/dist/chunks/show-on.js +358 -205
- package/dist/chunks/show-on.js.map +1 -1
- package/dist/chunks/timing.js +10 -0
- package/dist/chunks/timing.js.map +1 -0
- package/dist/chunks/tinymce.js +153 -203
- package/dist/chunks/tinymce.js.map +1 -1
- package/dist/chunks/ui-bootstrap5.js +58 -72
- package/dist/chunks/ui-bootstrap5.js.map +1 -1
- package/dist/chunks/ui.js +320 -0
- package/dist/chunks/ui.js.map +1 -0
- package/dist/chunks/unicorn.js.map +1 -1
- package/dist/chunks/useQueue.js +111 -0
- package/dist/chunks/useQueue.js.map +1 -0
- package/dist/chunks/useStack.js +76 -0
- package/dist/chunks/useStack.js.map +1 -0
- package/dist/chunks/validation.js +761 -853
- package/dist/chunks/validation.js.map +1 -1
- package/dist/editor.css +1 -1
- package/dist/index.d.ts +27 -15
- package/dist/multi-level-menu.css +1 -1
- package/dist/switcher.css +1 -1
- package/dist/unicorn.js +805 -130
- package/dist/unicorn.js.map +1 -1
- package/package.json +3 -3
- package/src/composable/useBsModalAlert.ts +92 -12
- package/src/composable/useHttp.ts +13 -1
- package/src/module/s3-uploader.ts +1 -1
- package/src/service/ui.ts +31 -15
- package/vite.config.ts +5 -1
- package/dist/chunks/_commonjsHelpers.js +0 -7
- package/dist/chunks/index.js +0 -314
- package/dist/chunks/isArguments.js +0 -146
- package/dist/chunks/unicorn.js +0 -2580
|
@@ -1,79 +1,82 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { t as mergeDeep } from "./arr.js";
|
|
2
|
+
import { o as html, s as injectCssToDocument } from "./dom.js";
|
|
3
|
+
import { r as simpleAlert } from "./alert.js";
|
|
4
|
+
import { i as uid } from "./crypto.js";
|
|
5
|
+
import { t as __ } from "./lang.js";
|
|
6
|
+
import { useUniDirective, watchAttributes } from "../unicorn.js";
|
|
7
|
+
//#region scss/field/file-drag.scss?inline
|
|
8
|
+
var file_drag_default = ".c-file-drag {\n --bs-card-border-color: var(--bs-gray-400);\n --fd-delete-color: var(--bs-danger);\n overflow: hidden;\n border: 1px solid var(--bs-card-border-color, #ddd);\n}\n.c-file-drag label {\n border: none;\n}\n\n.c-file-drag-input {\n position: relative;\n display: inline-block;\n width: 100%;\n min-height: 100px;\n cursor: pointer;\n}\n.c-file-drag-input input {\n position: relative;\n z-index: 2;\n width: 100%;\n margin: 0;\n overflow: hidden;\n opacity: 0;\n height: 100%;\n cursor: pointer;\n}\n.c-file-drag-input input.hover + label {\n background-color: #efefef;\n}\n.c-file-drag-input input.is-invalid ~ .c-file-drag-input__label {\n border-color: var(--bs-danger);\n}\n.c-file-drag-input input:disabled {\n opacity: 0;\n cursor: no-drop;\n}\n.c-file-drag-input input:disabled + label {\n background-color: #eee;\n color: #999;\n}\n.c-file-drag-input input:disabled + label button {\n display: none;\n}\n.c-file-drag-input__label {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 1;\n padding: 0.375rem 0.75rem;\n color: #495057;\n background-color: #fff;\n border: 1px solid var(--bs-gray-400);\n border-radius: 0.25rem;\n height: 100%;\n text-align: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n transition: all 0.3s;\n cursor: pointer;\n}\n.c-file-drag-input__label > span {\n display: inline-block;\n width: 100%;\n}\n.c-file-drag-input label::after {\n content: none !important;\n}\n.c-file-drag-preview .c-file-drag-preview__delete {\n --bs-link-color-rgb: var(--bs-dark-rgb);\n}\n.c-file-drag-preview .c-file-drag-preview__delete.active {\n --bs-link-color-rgb: var(--bs-primary-rgb);\n}";
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/module/field-file-drag.ts
|
|
11
|
+
var defaultOptions = {
|
|
12
|
+
maxFiles: void 0,
|
|
13
|
+
maxSize: void 0,
|
|
14
|
+
placeholder: "",
|
|
15
|
+
height: 125
|
|
8
16
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const name = this.getAttribute("name") || "file";
|
|
73
|
-
const inputId = this.id + "__input";
|
|
74
|
-
const btnText = __("unicorn.field.file.drag.button.text");
|
|
75
|
-
const input = html(`<input id="${inputId}" type="file" name="${name}" />`);
|
|
76
|
-
const label = html(`<label class="px-3 c-file-drag-input__label"
|
|
17
|
+
var FileDragElement = class extends HTMLElement {
|
|
18
|
+
static is = "uni-file-drag";
|
|
19
|
+
element;
|
|
20
|
+
overlayLabel;
|
|
21
|
+
button;
|
|
22
|
+
options;
|
|
23
|
+
get inputSelector() {
|
|
24
|
+
return this.getAttribute("selector") || "input[type=file]";
|
|
25
|
+
}
|
|
26
|
+
get multiple() {
|
|
27
|
+
return this.element.multiple;
|
|
28
|
+
}
|
|
29
|
+
connectedCallback() {
|
|
30
|
+
this.element = this.querySelector(this.inputSelector);
|
|
31
|
+
this.prepareElements();
|
|
32
|
+
const options = JSON.parse(this.getAttribute("options") || "{}") || {};
|
|
33
|
+
watchAttributes(this.element).watch("readonly", (el) => {
|
|
34
|
+
el.disabled = el.readOnly;
|
|
35
|
+
});
|
|
36
|
+
if (this.element.readOnly) this.element.disabled = true;
|
|
37
|
+
this.options = mergeDeep({}, defaultOptions, options);
|
|
38
|
+
this.bindEvent();
|
|
39
|
+
this.style.visibility = "";
|
|
40
|
+
this.style.height = (this.options.height || 100) + "px";
|
|
41
|
+
}
|
|
42
|
+
bindEvent() {
|
|
43
|
+
this.element.addEventListener("dragover", () => {
|
|
44
|
+
this.element.classList.add("hover");
|
|
45
|
+
});
|
|
46
|
+
this.element.addEventListener("dragleave", () => {
|
|
47
|
+
this.element.classList.remove("hover");
|
|
48
|
+
});
|
|
49
|
+
this.element.addEventListener("drop", () => {
|
|
50
|
+
this.element.classList.remove("hover");
|
|
51
|
+
});
|
|
52
|
+
this.onChange();
|
|
53
|
+
this.element.addEventListener("change", (e) => {
|
|
54
|
+
this.onChange(e);
|
|
55
|
+
});
|
|
56
|
+
this.element.addEventListener("input", (e) => {
|
|
57
|
+
this.onChange(e);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
prepareElements() {
|
|
61
|
+
if (this.children.length === 0) this.createElementsLayout();
|
|
62
|
+
this.overlayLabel = this.querySelector("[data-overlay-label]");
|
|
63
|
+
let button = this.overlayLabel.querySelector("button");
|
|
64
|
+
if (!button) {
|
|
65
|
+
button = document.createElement("button");
|
|
66
|
+
button.type = "button";
|
|
67
|
+
button.setAttribute("class", "c-file-drag-input__button btn btn-success btn-sm px-2 py-1");
|
|
68
|
+
button.innerText = __("unicorn.field.file.drag.button.text");
|
|
69
|
+
this.overlayLabel.appendChild(button);
|
|
70
|
+
}
|
|
71
|
+
this.button = button;
|
|
72
|
+
}
|
|
73
|
+
createElementsLayout() {
|
|
74
|
+
this.id ||= "c-file-drag-" + uid();
|
|
75
|
+
const name = this.getAttribute("name") || "file";
|
|
76
|
+
const inputId = this.id + "__input";
|
|
77
|
+
const btnText = __("unicorn.field.file.drag.button.text");
|
|
78
|
+
const input = html(`<input id="${inputId}" type="file" name="${name}" />`);
|
|
79
|
+
const label = html(`<label class="px-3 c-file-drag-input__label"
|
|
77
80
|
data-overlay-label
|
|
78
81
|
for="${inputId}">
|
|
79
82
|
<span class="label-text d-block">
|
|
@@ -83,139 +86,102 @@ class FileDragElement extends HTMLElement {
|
|
|
83
86
|
${btnText}
|
|
84
87
|
</button>
|
|
85
88
|
</label>`);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (type.indexOf("/") !== -1) {
|
|
150
|
-
if (this.compareMimeType(type, file.type)) {
|
|
151
|
-
allow = true;
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
if (type.toLowerCase() === fileExt.toLowerCase()) {
|
|
155
|
-
allow = true;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
if (!allow) {
|
|
160
|
-
this.alert(
|
|
161
|
-
__("unicorn.field.file.drag.message.unaccepted.files"),
|
|
162
|
-
__("unicorn.field.file.drag.message.unaccepted.files.desc", accepted.join(", ")),
|
|
163
|
-
"warning"
|
|
164
|
-
);
|
|
165
|
-
throw new Error("Not accepted file ext");
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
compareMimeType(accepted, mime) {
|
|
170
|
-
const accepted2 = accepted.split("/");
|
|
171
|
-
const mime2 = mime.split("/");
|
|
172
|
-
if (accepted2[1] === "*") {
|
|
173
|
-
return accepted2[0] === mime2[0];
|
|
174
|
-
}
|
|
175
|
-
return accepted === mime;
|
|
176
|
-
}
|
|
177
|
-
async alert(title, text = "", type = "info") {
|
|
178
|
-
await simpleAlert(title, text, type);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
89
|
+
this.element = input;
|
|
90
|
+
this.overlayLabel = label;
|
|
91
|
+
this.appendChild(input);
|
|
92
|
+
this.appendChild(label);
|
|
93
|
+
}
|
|
94
|
+
onChange(evt) {
|
|
95
|
+
const files = this.element.files || [];
|
|
96
|
+
const limit = this.options.maxFiles;
|
|
97
|
+
const maxSize = this.options.maxSize;
|
|
98
|
+
let placeholder = this.options.placeholder;
|
|
99
|
+
const accepted = (this.element.getAttribute("accept") || this.element.getAttribute("data-accepted") || "").split(",").map((v) => v.trim()).filter((v) => v.length > 0).map((v) => {
|
|
100
|
+
if (v.indexOf("/") === -1 && v[0] === ".") return v.substring(1);
|
|
101
|
+
return v;
|
|
102
|
+
});
|
|
103
|
+
let text;
|
|
104
|
+
if (!placeholder) if (this.multiple) placeholder = __("unicorn.field.file.drag.placeholder.multiple");
|
|
105
|
+
else placeholder = __("unicorn.field.file.drag.placeholder.single");
|
|
106
|
+
if (limit && files.length > limit) {
|
|
107
|
+
this.alert(__("unicorn.field.file.drag.message.max.files", limit), "", "warning");
|
|
108
|
+
evt?.preventDefault();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
let fileSize = 0;
|
|
112
|
+
Array.prototype.forEach.call(files, (file) => {
|
|
113
|
+
this.checkFileType(accepted, file);
|
|
114
|
+
fileSize += file.size;
|
|
115
|
+
});
|
|
116
|
+
if (maxSize && fileSize / 1024 / 1024 > maxSize) {
|
|
117
|
+
this.alert(__("unicorn.field.file.drag.message.max.size", maxSize < 1 ? maxSize * 1024 + "KB" : maxSize + "MB"), "", "warning");
|
|
118
|
+
evt?.preventDefault();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (files.length > 1) text = `<span class="fa fa-files fa-copy"></span> ${__("unicorn.field.file.drag.selected", files.length)}`;
|
|
122
|
+
else if (files.length === 1) text = `<span class="fa fa-file"></span> ${files[0].name}`;
|
|
123
|
+
else text = `<span class="fa fa-upload"></span> ${placeholder}`;
|
|
124
|
+
this.overlayLabel.querySelector("span").innerHTML = text;
|
|
125
|
+
}
|
|
126
|
+
checkFileType(accepted, file) {
|
|
127
|
+
const fileExt = file.name.split(".").pop() || "";
|
|
128
|
+
if (accepted.length) {
|
|
129
|
+
let allow = false;
|
|
130
|
+
accepted.forEach((type) => {
|
|
131
|
+
if (allow) return;
|
|
132
|
+
if (type.indexOf("/") !== -1) {
|
|
133
|
+
if (this.compareMimeType(type, file.type)) allow = true;
|
|
134
|
+
} else if (type.toLowerCase() === fileExt.toLowerCase()) allow = true;
|
|
135
|
+
});
|
|
136
|
+
if (!allow) {
|
|
137
|
+
this.alert(__("unicorn.field.file.drag.message.unaccepted.files"), __("unicorn.field.file.drag.message.unaccepted.files.desc", accepted.join(", ")), "warning");
|
|
138
|
+
throw new Error("Not accepted file ext");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
compareMimeType(accepted, mime) {
|
|
143
|
+
const accepted2 = accepted.split("/");
|
|
144
|
+
const mime2 = mime.split("/");
|
|
145
|
+
if (accepted2[1] === "*") return accepted2[0] === mime2[0];
|
|
146
|
+
return accepted === mime;
|
|
147
|
+
}
|
|
148
|
+
async alert(title, text = "", type = "info") {
|
|
149
|
+
await simpleAlert(title, text, type);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
181
152
|
async function init() {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
});
|
|
153
|
+
injectCssToDocument(document, file_drag_default);
|
|
154
|
+
customElements.define(FileDragElement.is, FileDragElement);
|
|
155
|
+
return useUniDirective("file-drag-field", { mounted(el) {
|
|
156
|
+
const input = el.querySelector("input[type=file]");
|
|
157
|
+
const placeholderInput = el.querySelector("[data-role=placeholder]");
|
|
158
|
+
const preview = el.querySelector(".c-file-drag-preview");
|
|
159
|
+
if (preview) {
|
|
160
|
+
const previewLink = preview.querySelector(".c-file-drag-preview__link");
|
|
161
|
+
const delButton = preview.querySelector(".c-file-drag-preview__delete");
|
|
162
|
+
let inputValue = placeholderInput.value;
|
|
163
|
+
let required = input.required;
|
|
164
|
+
if (placeholderInput.value) input.required = false;
|
|
165
|
+
delButton.addEventListener("click", () => {
|
|
166
|
+
if (delButton.classList.contains("active")) {
|
|
167
|
+
previewLink.style.textDecoration = "";
|
|
168
|
+
previewLink.style.setProperty("color", "");
|
|
169
|
+
placeholderInput.value = inputValue;
|
|
170
|
+
delButton.classList.remove("active");
|
|
171
|
+
input.required = false;
|
|
172
|
+
} else {
|
|
173
|
+
previewLink.style.textDecoration = "line-through";
|
|
174
|
+
previewLink.style.color = "var(--fd-delete-color, var(--bs-danger))";
|
|
175
|
+
placeholderInput.value = "";
|
|
176
|
+
delButton.classList.add("active");
|
|
177
|
+
input.required = required;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
} });
|
|
215
182
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
//# sourceMappingURL=field-file-drag.js.map
|
|
183
|
+
var ready = /* @__PURE__ */ init();
|
|
184
|
+
//#endregion
|
|
185
|
+
export { FileDragElement, ready };
|
|
186
|
+
|
|
187
|
+
//# sourceMappingURL=field-file-drag.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-file-drag.js","sources":["../../src/module/field-file-drag.ts"],"sourcesContent":["import css from '../../scss/field/file-drag.scss?inline';\nimport { useUniDirective } from '../composable';\nimport { __, html, injectCssToDocument, simpleAlert, uid, watchAttributes } from '../service';\nimport { mergeDeep } from '../utilities';\n\nexport interface FileDragOptions {\n maxFiles: number | undefined;\n maxSize: number | undefined;\n placeholder: string;\n height: number;\n}\n\nconst defaultOptions: FileDragOptions = {\n maxFiles: undefined,\n maxSize: undefined,\n placeholder: '',\n height: 125,\n}\n\nexport class FileDragElement extends HTMLElement {\n static is = 'uni-file-drag';\n\n element!: HTMLInputElement;\n overlayLabel!: HTMLLabelElement;\n button!: HTMLButtonElement;\n options!: FileDragOptions;\n\n get inputSelector() {\n return this.getAttribute('selector') || 'input[type=file]';\n }\n\n get multiple() {\n return this.element.multiple;\n }\n\n connectedCallback(): void {\n this.element = this.querySelector(this.inputSelector)!;\n\n this.prepareElements();\n\n const options = JSON.parse(this.getAttribute('options') || '{}') || {};\n\n const observer = watchAttributes(this.element);\n observer.watch('readonly', (el) => {\n el.disabled = el.readOnly;\n });\n\n if (this.element.readOnly) {\n this.element.disabled = true;\n }\n\n this.options = mergeDeep({}, defaultOptions, options);\n\n this.bindEvent();\n\n this.style.visibility = '';\n\n this.style.height = (this.options.height || 100) + 'px';\n }\n\n bindEvent() {\n this.element.addEventListener('dragover', () => {\n this.element.classList.add('hover');\n });\n\n this.element.addEventListener('dragleave', () => {\n this.element.classList.remove('hover');\n });\n\n this.element.addEventListener('drop', () => {\n this.element.classList.remove('hover');\n });\n\n this.onChange();\n\n this.element.addEventListener('change', (e) => {\n this.onChange(e);\n });\n this.element.addEventListener('input', (e) => {\n this.onChange(e);\n });\n }\n\n prepareElements() {\n if (this.children.length === 0) {\n this.createElementsLayout();\n }\n\n this.overlayLabel = this.querySelector<HTMLLabelElement>('[data-overlay-label]')!;\n\n let button = this.overlayLabel.querySelector('button');\n\n // B/C for new file drag style\n if (!button) {\n button = document.createElement('button');\n button.type = 'button';\n button.setAttribute('class', 'c-file-drag-input__button btn btn-success btn-sm px-2 py-1');\n button.innerText = __('unicorn.field.file.drag.button.text');\n this.overlayLabel.appendChild(button);\n }\n\n this.button = button;\n }\n\n createElementsLayout() {\n this.id ||= 'c-file-drag-' + uid();\n const name = this.getAttribute('name') || 'file';\n const inputId = this.id + '__input';\n const btnText = __('unicorn.field.file.drag.button.text');\n\n const input = html(`<input id=\"${inputId}\" type=\"file\" name=\"${name}\" />`);\n const label = html(`<label class=\"px-3 c-file-drag-input__label\"\n data-overlay-label\n for=\"${inputId}\">\n <span class=\"label-text d-block\">\n <span class=\"fa fa-upload\"></span>\n </span>\n <button type=\"button\" class=\"c-file-drag-input__button btn btn-success btn-sm px-2 py-1\">\n ${btnText}\n </button>\n </label>`);\n\n this.element = input as HTMLInputElement;\n this.overlayLabel = label as HTMLLabelElement;\n\n this.appendChild(input);\n this.appendChild(label);\n }\n\n onChange(evt?: Event) {\n const files = this.element.files || [];\n const limit = this.options.maxFiles;\n const maxSize = this.options.maxSize;\n let placeholder = this.options.placeholder;\n\n const accepted = (this.element.getAttribute('accept') || this.element.getAttribute('data-accepted') || '')\n .split(',')\n .map(v => v.trim())\n .filter(v => v.length > 0)\n .map(v => {\n if (v.indexOf('/') === -1 && v[0] === '.') {\n return v.substring(1);\n }\n\n return v;\n });\n\n let text: string;\n\n if (!placeholder) {\n if (this.multiple) {\n placeholder = __('unicorn.field.file.drag.placeholder.multiple');\n } else {\n placeholder = __('unicorn.field.file.drag.placeholder.single');\n }\n }\n\n // Files limit\n if (limit && files.length > limit) {\n this.alert(__('unicorn.field.file.drag.message.max.files', limit), '', 'warning');\n evt?.preventDefault();\n return;\n }\n\n // Files size\n let fileSize = 0;\n Array.prototype.forEach.call(files, file => {\n this.checkFileType(accepted, file);\n\n fileSize += file.size;\n });\n\n if (maxSize && (fileSize / 1024 / 1024) > maxSize) {\n this.alert(\n __(\n 'unicorn.field.file.drag.message.max.size',\n maxSize < 1 ? (maxSize * 1024) + 'KB' : maxSize + 'MB'\n ),\n '',\n 'warning'\n );\n evt?.preventDefault();\n return;\n }\n\n if (files.length > 1) {\n text = `<span class=\"fa fa-files fa-copy\"></span> ${__('unicorn.field.file.drag.selected', files.length)}`;\n } else if (files.length === 1) {\n text = `<span class=\"fa fa-file\"></span> ${files[0].name}`;\n } else {\n text = `<span class=\"fa fa-upload\"></span> ${placeholder}`;\n }\n\n //replace the \"Choose a file\" label\n this.overlayLabel.querySelector<HTMLSpanElement>('span')!.innerHTML = text;\n }\n\n checkFileType(accepted: string[], file: File) {\n const fileExt = file.name.split('.').pop() || '';\n\n if (accepted.length) {\n let allow = false;\n\n accepted.forEach((type) => {\n if (allow) {\n return;\n }\n\n if (type.indexOf('/') !== -1) {\n if (this.compareMimeType(type, file.type)) {\n allow = true;\n }\n } else {\n if (type.toLowerCase() === fileExt.toLowerCase()) {\n allow = true;\n }\n }\n });\n\n if (!allow) {\n this.alert(\n __('unicorn.field.file.drag.message.unaccepted.files'),\n __('unicorn.field.file.drag.message.unaccepted.files.desc', accepted.join(', ')),\n 'warning'\n );\n throw new Error('Not accepted file ext');\n }\n }\n }\n\n compareMimeType(accepted: string, mime: string) {\n const accepted2 = accepted.split('/');\n const mime2 = mime.split('/');\n\n if (accepted2[1] === '*') {\n return accepted2[0] === mime2[0];\n }\n\n return accepted === mime;\n }\n\n async alert(title: string, text: string = '', type: string = 'info') {\n await simpleAlert(title, text, type);\n }\n}\n\nasync function init() {\n injectCssToDocument(document, css);\n customElements.define(FileDragElement.is, FileDragElement);\n\n return useUniDirective('file-drag-field', {\n mounted(el) {\n const input = el.querySelector<HTMLInputElement>('input[type=file]')!;\n const placeholderInput = el.querySelector<HTMLInputElement>('[data-role=placeholder]')!;\n\n const preview = el.querySelector('.c-file-drag-preview');\n\n if (preview) {\n const previewLink = preview.querySelector<HTMLAnchorElement>('.c-file-drag-preview__link')!;\n const delButton = preview.querySelector<HTMLAnchorElement>('.c-file-drag-preview__delete')!;\n // let linkTitle = previewLink.textContent;\n let inputValue = placeholderInput.value;\n let required = input.required;\n\n if (placeholderInput.value) {\n input.required = false;\n }\n\n delButton.addEventListener('click', () => {\n if (delButton.classList.contains('active')) {\n // Restore\n previewLink.style.textDecoration = '';\n previewLink.style.setProperty('color', '');\n placeholderInput.value = inputValue;\n delButton.classList.remove('active');\n input.required = false;\n } else {\n // Delete\n previewLink.style.textDecoration = 'line-through';\n previewLink.style.color = 'var(--fd-delete-color, var(--bs-danger))';\n placeholderInput.value = '';\n delButton.classList.add('active');\n input.required = required;\n }\n });\n }\n }\n });\n}\n\nexport const ready = init();\n\nexport interface FileDragModule {\n FileDragElement: typeof FileDragElement;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"field-file-drag.js","names":[],"sources":["../../scss/field/file-drag.scss?inline","../../src/module/field-file-drag.ts"],"sourcesContent":[".c-file-drag {\n --bs-card-border-color: var(--bs-gray-400);\n --fd-delete-color: var(--bs-danger);\n\n overflow: hidden;\n border: 1px solid var(--bs-card-border-color, #ddd);\n\n label {\n border: none;\n }\n}\n\n.c-file-drag-input {\n position: relative;\n display: inline-block;\n width: 100%;\n min-height: 100px;\n cursor: pointer;\n\n input {\n position: relative;\n z-index: 2;\n width: 100%;\n margin: 0;\n overflow: hidden;\n opacity: 0;\n height: 100%;\n cursor: pointer;\n\n &.hover + label {\n background-color: #efefef;\n }\n\n &.is-invalid ~ .c-file-drag-input__label {\n border-color: var(--bs-danger);\n }\n\n &:disabled {\n opacity: 0;\n cursor: no-drop;\n\n + label {\n background-color: #eee;\n color: #999;\n }\n\n + label button {\n display: none;\n }\n }\n }\n\n &__label {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 1;\n padding: .375rem .75rem;\n color: #495057;\n background-color: #fff;\n border: 1px solid var(--bs-gray-400);\n border-radius: .25rem;\n height: 100%;\n text-align: center;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: .5rem;\n transition: all .3s;\n cursor: pointer;\n\n > span {\n display: inline-block;\n width: 100%;\n }\n }\n\n label::after {\n content: none !important;\n }\n\n &__button {\n //font-size: .85rem;\n //padding: .25rem .5rem;\n\n //--bs-btn-border-color: var(--bs-secondary);\n //--bs-btn-color: var(--bs-secondary);\n }\n}\n\n.c-file-drag-preview {\n .c-file-drag-preview__delete {\n --bs-link-color-rgb: var(--bs-dark-rgb);\n\n &.active {\n --bs-link-color-rgb: var(--bs-primary-rgb);\n }\n }\n}\n","import css from '../../scss/field/file-drag.scss?inline';\nimport { useUniDirective } from '../composable';\nimport { __, html, injectCssToDocument, simpleAlert, uid, watchAttributes } from '../service';\nimport { mergeDeep } from '../utilities';\n\nexport interface FileDragOptions {\n maxFiles: number | undefined;\n maxSize: number | undefined;\n placeholder: string;\n height: number;\n}\n\nconst defaultOptions: FileDragOptions = {\n maxFiles: undefined,\n maxSize: undefined,\n placeholder: '',\n height: 125,\n}\n\nexport class FileDragElement extends HTMLElement {\n static is = 'uni-file-drag';\n\n element!: HTMLInputElement;\n overlayLabel!: HTMLLabelElement;\n button!: HTMLButtonElement;\n options!: FileDragOptions;\n\n get inputSelector() {\n return this.getAttribute('selector') || 'input[type=file]';\n }\n\n get multiple() {\n return this.element.multiple;\n }\n\n connectedCallback(): void {\n this.element = this.querySelector(this.inputSelector)!;\n\n this.prepareElements();\n\n const options = JSON.parse(this.getAttribute('options') || '{}') || {};\n\n const observer = watchAttributes(this.element);\n observer.watch('readonly', (el) => {\n el.disabled = el.readOnly;\n });\n\n if (this.element.readOnly) {\n this.element.disabled = true;\n }\n\n this.options = mergeDeep({}, defaultOptions, options);\n\n this.bindEvent();\n\n this.style.visibility = '';\n\n this.style.height = (this.options.height || 100) + 'px';\n }\n\n bindEvent() {\n this.element.addEventListener('dragover', () => {\n this.element.classList.add('hover');\n });\n\n this.element.addEventListener('dragleave', () => {\n this.element.classList.remove('hover');\n });\n\n this.element.addEventListener('drop', () => {\n this.element.classList.remove('hover');\n });\n\n this.onChange();\n\n this.element.addEventListener('change', (e) => {\n this.onChange(e);\n });\n this.element.addEventListener('input', (e) => {\n this.onChange(e);\n });\n }\n\n prepareElements() {\n if (this.children.length === 0) {\n this.createElementsLayout();\n }\n\n this.overlayLabel = this.querySelector<HTMLLabelElement>('[data-overlay-label]')!;\n\n let button = this.overlayLabel.querySelector('button');\n\n // B/C for new file drag style\n if (!button) {\n button = document.createElement('button');\n button.type = 'button';\n button.setAttribute('class', 'c-file-drag-input__button btn btn-success btn-sm px-2 py-1');\n button.innerText = __('unicorn.field.file.drag.button.text');\n this.overlayLabel.appendChild(button);\n }\n\n this.button = button;\n }\n\n createElementsLayout() {\n this.id ||= 'c-file-drag-' + uid();\n const name = this.getAttribute('name') || 'file';\n const inputId = this.id + '__input';\n const btnText = __('unicorn.field.file.drag.button.text');\n\n const input = html(`<input id=\"${inputId}\" type=\"file\" name=\"${name}\" />`);\n const label = html(`<label class=\"px-3 c-file-drag-input__label\"\n data-overlay-label\n for=\"${inputId}\">\n <span class=\"label-text d-block\">\n <span class=\"fa fa-upload\"></span>\n </span>\n <button type=\"button\" class=\"c-file-drag-input__button btn btn-success btn-sm px-2 py-1\">\n ${btnText}\n </button>\n </label>`);\n\n this.element = input as HTMLInputElement;\n this.overlayLabel = label as HTMLLabelElement;\n\n this.appendChild(input);\n this.appendChild(label);\n }\n\n onChange(evt?: Event) {\n const files = this.element.files || [];\n const limit = this.options.maxFiles;\n const maxSize = this.options.maxSize;\n let placeholder = this.options.placeholder;\n\n const accepted = (this.element.getAttribute('accept') || this.element.getAttribute('data-accepted') || '')\n .split(',')\n .map(v => v.trim())\n .filter(v => v.length > 0)\n .map(v => {\n if (v.indexOf('/') === -1 && v[0] === '.') {\n return v.substring(1);\n }\n\n return v;\n });\n\n let text: string;\n\n if (!placeholder) {\n if (this.multiple) {\n placeholder = __('unicorn.field.file.drag.placeholder.multiple');\n } else {\n placeholder = __('unicorn.field.file.drag.placeholder.single');\n }\n }\n\n // Files limit\n if (limit && files.length > limit) {\n this.alert(__('unicorn.field.file.drag.message.max.files', limit), '', 'warning');\n evt?.preventDefault();\n return;\n }\n\n // Files size\n let fileSize = 0;\n Array.prototype.forEach.call(files, file => {\n this.checkFileType(accepted, file);\n\n fileSize += file.size;\n });\n\n if (maxSize && (fileSize / 1024 / 1024) > maxSize) {\n this.alert(\n __(\n 'unicorn.field.file.drag.message.max.size',\n maxSize < 1 ? (maxSize * 1024) + 'KB' : maxSize + 'MB'\n ),\n '',\n 'warning'\n );\n evt?.preventDefault();\n return;\n }\n\n if (files.length > 1) {\n text = `<span class=\"fa fa-files fa-copy\"></span> ${__('unicorn.field.file.drag.selected', files.length)}`;\n } else if (files.length === 1) {\n text = `<span class=\"fa fa-file\"></span> ${files[0].name}`;\n } else {\n text = `<span class=\"fa fa-upload\"></span> ${placeholder}`;\n }\n\n //replace the \"Choose a file\" label\n this.overlayLabel.querySelector<HTMLSpanElement>('span')!.innerHTML = text;\n }\n\n checkFileType(accepted: string[], file: File) {\n const fileExt = file.name.split('.').pop() || '';\n\n if (accepted.length) {\n let allow = false;\n\n accepted.forEach((type) => {\n if (allow) {\n return;\n }\n\n if (type.indexOf('/') !== -1) {\n if (this.compareMimeType(type, file.type)) {\n allow = true;\n }\n } else {\n if (type.toLowerCase() === fileExt.toLowerCase()) {\n allow = true;\n }\n }\n });\n\n if (!allow) {\n this.alert(\n __('unicorn.field.file.drag.message.unaccepted.files'),\n __('unicorn.field.file.drag.message.unaccepted.files.desc', accepted.join(', ')),\n 'warning'\n );\n throw new Error('Not accepted file ext');\n }\n }\n }\n\n compareMimeType(accepted: string, mime: string) {\n const accepted2 = accepted.split('/');\n const mime2 = mime.split('/');\n\n if (accepted2[1] === '*') {\n return accepted2[0] === mime2[0];\n }\n\n return accepted === mime;\n }\n\n async alert(title: string, text: string = '', type: string = 'info') {\n await simpleAlert(title, text, type);\n }\n}\n\nasync function init() {\n injectCssToDocument(document, css);\n customElements.define(FileDragElement.is, FileDragElement);\n\n return useUniDirective('file-drag-field', {\n mounted(el) {\n const input = el.querySelector<HTMLInputElement>('input[type=file]')!;\n const placeholderInput = el.querySelector<HTMLInputElement>('[data-role=placeholder]')!;\n\n const preview = el.querySelector('.c-file-drag-preview');\n\n if (preview) {\n const previewLink = preview.querySelector<HTMLAnchorElement>('.c-file-drag-preview__link')!;\n const delButton = preview.querySelector<HTMLAnchorElement>('.c-file-drag-preview__delete')!;\n // let linkTitle = previewLink.textContent;\n let inputValue = placeholderInput.value;\n let required = input.required;\n\n if (placeholderInput.value) {\n input.required = false;\n }\n\n delButton.addEventListener('click', () => {\n if (delButton.classList.contains('active')) {\n // Restore\n previewLink.style.textDecoration = '';\n previewLink.style.setProperty('color', '');\n placeholderInput.value = inputValue;\n delButton.classList.remove('active');\n input.required = false;\n } else {\n // Delete\n previewLink.style.textDecoration = 'line-through';\n previewLink.style.color = 'var(--fd-delete-color, var(--bs-danger))';\n placeholderInput.value = '';\n delButton.classList.add('active');\n input.required = required;\n }\n });\n }\n }\n });\n}\n\nexport const ready = init();\n\nexport interface FileDragModule {\n FileDragElement: typeof FileDragElement;\n}\n"],"mappings":"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"}
|