@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.
Files changed (108) hide show
  1. package/dist/chunks/_arrayPush.js +325 -108
  2. package/dist/chunks/_arrayPush.js.map +1 -1
  3. package/dist/chunks/_baseRest.js +155 -60
  4. package/dist/chunks/_baseRest.js.map +1 -1
  5. package/dist/chunks/_baseUnary.js +463 -0
  6. package/dist/chunks/_baseUnary.js.map +1 -0
  7. package/dist/chunks/_getPrototype.js +292 -100
  8. package/dist/chunks/_getPrototype.js.map +1 -1
  9. package/dist/chunks/alert-adapter.js +29 -0
  10. package/dist/chunks/alert-adapter.js.map +1 -0
  11. package/dist/chunks/alert.js +21 -0
  12. package/dist/chunks/alert.js.map +1 -0
  13. package/dist/chunks/arr.js +24 -0
  14. package/dist/chunks/arr.js.map +1 -0
  15. package/dist/chunks/button-radio.js +127 -145
  16. package/dist/chunks/button-radio.js.map +1 -1
  17. package/dist/chunks/checkboxes-multi-select.js +44 -43
  18. package/dist/chunks/checkboxes-multi-select.js.map +1 -1
  19. package/dist/chunks/chunk.js +24 -0
  20. package/dist/chunks/cloneDeep.js +679 -212
  21. package/dist/chunks/cloneDeep.js.map +1 -1
  22. package/dist/chunks/cropper.min.js +6 -5
  23. package/dist/chunks/cropper.min.js.map +1 -1
  24. package/dist/chunks/crypto.js +26 -0
  25. package/dist/chunks/crypto.js.map +1 -0
  26. package/dist/chunks/data.js +49 -0
  27. package/dist/chunks/data.js.map +1 -0
  28. package/dist/chunks/dom.js +128 -0
  29. package/dist/chunks/dom.js.map +1 -0
  30. package/dist/chunks/events.js +270 -0
  31. package/dist/chunks/events.js.map +1 -0
  32. package/dist/chunks/field-cascade-select.js +207 -250
  33. package/dist/chunks/field-cascade-select.js.map +1 -1
  34. package/dist/chunks/field-file-drag.js +175 -209
  35. package/dist/chunks/field-file-drag.js.map +1 -1
  36. package/dist/chunks/field-flatpickr.js +94 -898
  37. package/dist/chunks/field-flatpickr.js.map +1 -1
  38. package/dist/chunks/field-modal-select.js +728 -467
  39. package/dist/chunks/field-modal-select.js.map +1 -1
  40. package/dist/chunks/field-modal-tree.js +771 -766
  41. package/dist/chunks/field-modal-tree.js.map +1 -1
  42. package/dist/chunks/field-multi-uploader.js +249 -256
  43. package/dist/chunks/field-multi-uploader.js.map +1 -1
  44. package/dist/chunks/field-repeatable.js +111 -127
  45. package/dist/chunks/field-repeatable.js.map +1 -1
  46. package/dist/chunks/field-single-image-drag.js +286 -338
  47. package/dist/chunks/field-single-image-drag.js.map +1 -1
  48. package/dist/chunks/form.js +146 -159
  49. package/dist/chunks/form.js.map +1 -1
  50. package/dist/chunks/grid.js +349 -418
  51. package/dist/chunks/grid.js.map +1 -1
  52. package/dist/chunks/helper.js +39 -0
  53. package/dist/chunks/helper.js.map +1 -0
  54. package/dist/chunks/http-client.js +221 -211
  55. package/dist/chunks/http-client.js.map +1 -1
  56. package/dist/chunks/iframe-modal.js +95 -115
  57. package/dist/chunks/iframe-modal.js.map +1 -1
  58. package/dist/chunks/keep-tab.js +92 -101
  59. package/dist/chunks/keep-tab.js.map +1 -1
  60. package/dist/chunks/lang.js +250 -0
  61. package/dist/chunks/lang.js.map +1 -0
  62. package/dist/chunks/legacy.js +197 -201
  63. package/dist/chunks/legacy.js.map +1 -1
  64. package/dist/chunks/list-dependent.js +195 -228
  65. package/dist/chunks/list-dependent.js.map +1 -1
  66. package/dist/chunks/loader.js +106 -0
  67. package/dist/chunks/loader.js.map +1 -0
  68. package/dist/chunks/monthSelect.js +251 -0
  69. package/dist/chunks/monthSelect.js.map +1 -0
  70. package/dist/chunks/router.js +111 -0
  71. package/dist/chunks/router.js.map +1 -0
  72. package/dist/chunks/s3-multipart-uploader.js +183 -210
  73. package/dist/chunks/s3-multipart-uploader.js.map +1 -1
  74. package/dist/chunks/s3-uploader.js +106 -128
  75. package/dist/chunks/s3-uploader.js.map +1 -1
  76. package/dist/chunks/show-on.js +358 -205
  77. package/dist/chunks/show-on.js.map +1 -1
  78. package/dist/chunks/timing.js +10 -0
  79. package/dist/chunks/timing.js.map +1 -0
  80. package/dist/chunks/tinymce.js +153 -203
  81. package/dist/chunks/tinymce.js.map +1 -1
  82. package/dist/chunks/ui-bootstrap5.js +58 -72
  83. package/dist/chunks/ui-bootstrap5.js.map +1 -1
  84. package/dist/chunks/ui.js +320 -0
  85. package/dist/chunks/ui.js.map +1 -0
  86. package/dist/chunks/unicorn.js.map +1 -1
  87. package/dist/chunks/useQueue.js +111 -0
  88. package/dist/chunks/useQueue.js.map +1 -0
  89. package/dist/chunks/useStack.js +76 -0
  90. package/dist/chunks/useStack.js.map +1 -0
  91. package/dist/chunks/validation.js +761 -853
  92. package/dist/chunks/validation.js.map +1 -1
  93. package/dist/editor.css +1 -1
  94. package/dist/index.d.ts +27 -15
  95. package/dist/multi-level-menu.css +1 -1
  96. package/dist/switcher.css +1 -1
  97. package/dist/unicorn.js +805 -130
  98. package/dist/unicorn.js.map +1 -1
  99. package/package.json +3 -3
  100. package/src/composable/useBsModalAlert.ts +92 -12
  101. package/src/composable/useHttp.ts +13 -1
  102. package/src/module/s3-uploader.ts +1 -1
  103. package/src/service/ui.ts +31 -15
  104. package/vite.config.ts +5 -1
  105. package/dist/chunks/_commonjsHelpers.js +0 -7
  106. package/dist/chunks/index.js +0 -314
  107. package/dist/chunks/isArguments.js +0 -146
  108. package/dist/chunks/unicorn.js +0 -2580
@@ -1,79 +1,82 @@
1
- import { aa as watchAttributes, a6 as mergeDeep, _ as __, K as uid, B as html, G as simpleAlert, ab as injectCssToDocument, a as useUniDirective } from "./unicorn.js";
2
- const css = ".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}";
3
- const defaultOptions = {
4
- maxFiles: void 0,
5
- maxSize: void 0,
6
- placeholder: "",
7
- height: 125
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
- class FileDragElement extends HTMLElement {
10
- static is = "uni-file-drag";
11
- element;
12
- overlayLabel;
13
- button;
14
- options;
15
- get inputSelector() {
16
- return this.getAttribute("selector") || "input[type=file]";
17
- }
18
- get multiple() {
19
- return this.element.multiple;
20
- }
21
- connectedCallback() {
22
- this.element = this.querySelector(this.inputSelector);
23
- this.prepareElements();
24
- const options = JSON.parse(this.getAttribute("options") || "{}") || {};
25
- const observer = watchAttributes(this.element);
26
- observer.watch("readonly", (el) => {
27
- el.disabled = el.readOnly;
28
- });
29
- if (this.element.readOnly) {
30
- this.element.disabled = true;
31
- }
32
- this.options = mergeDeep({}, defaultOptions, options);
33
- this.bindEvent();
34
- this.style.visibility = "";
35
- this.style.height = (this.options.height || 100) + "px";
36
- }
37
- bindEvent() {
38
- this.element.addEventListener("dragover", () => {
39
- this.element.classList.add("hover");
40
- });
41
- this.element.addEventListener("dragleave", () => {
42
- this.element.classList.remove("hover");
43
- });
44
- this.element.addEventListener("drop", () => {
45
- this.element.classList.remove("hover");
46
- });
47
- this.onChange();
48
- this.element.addEventListener("change", (e) => {
49
- this.onChange(e);
50
- });
51
- this.element.addEventListener("input", (e) => {
52
- this.onChange(e);
53
- });
54
- }
55
- prepareElements() {
56
- if (this.children.length === 0) {
57
- this.createElementsLayout();
58
- }
59
- this.overlayLabel = this.querySelector("[data-overlay-label]");
60
- let button = this.overlayLabel.querySelector("button");
61
- if (!button) {
62
- button = document.createElement("button");
63
- button.type = "button";
64
- button.setAttribute("class", "c-file-drag-input__button btn btn-success btn-sm px-2 py-1");
65
- button.innerText = __("unicorn.field.file.drag.button.text");
66
- this.overlayLabel.appendChild(button);
67
- }
68
- this.button = button;
69
- }
70
- createElementsLayout() {
71
- this.id ||= "c-file-drag-" + uid();
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
- this.element = input;
87
- this.overlayLabel = label;
88
- this.appendChild(input);
89
- this.appendChild(label);
90
- }
91
- onChange(evt) {
92
- const files = this.element.files || [];
93
- const limit = this.options.maxFiles;
94
- const maxSize = this.options.maxSize;
95
- let placeholder = this.options.placeholder;
96
- const accepted = (this.element.getAttribute("accept") || this.element.getAttribute("data-accepted") || "").split(",").map((v) => v.trim()).filter((v) => v.length > 0).map((v) => {
97
- if (v.indexOf("/") === -1 && v[0] === ".") {
98
- return v.substring(1);
99
- }
100
- return v;
101
- });
102
- let text;
103
- if (!placeholder) {
104
- if (this.multiple) {
105
- placeholder = __("unicorn.field.file.drag.placeholder.multiple");
106
- } else {
107
- placeholder = __("unicorn.field.file.drag.placeholder.single");
108
- }
109
- }
110
- if (limit && files.length > limit) {
111
- this.alert(__("unicorn.field.file.drag.message.max.files", limit), "", "warning");
112
- evt?.preventDefault();
113
- return;
114
- }
115
- let fileSize = 0;
116
- Array.prototype.forEach.call(files, (file) => {
117
- this.checkFileType(accepted, file);
118
- fileSize += file.size;
119
- });
120
- if (maxSize && fileSize / 1024 / 1024 > maxSize) {
121
- this.alert(
122
- __(
123
- "unicorn.field.file.drag.message.max.size",
124
- maxSize < 1 ? maxSize * 1024 + "KB" : maxSize + "MB"
125
- ),
126
- "",
127
- "warning"
128
- );
129
- evt?.preventDefault();
130
- return;
131
- }
132
- if (files.length > 1) {
133
- text = `<span class="fa fa-files fa-copy"></span> ${__("unicorn.field.file.drag.selected", files.length)}`;
134
- } else if (files.length === 1) {
135
- text = `<span class="fa fa-file"></span> ${files[0].name}`;
136
- } else {
137
- text = `<span class="fa fa-upload"></span> ${placeholder}`;
138
- }
139
- this.overlayLabel.querySelector("span").innerHTML = text;
140
- }
141
- checkFileType(accepted, file) {
142
- const fileExt = file.name.split(".").pop() || "";
143
- if (accepted.length) {
144
- let allow = false;
145
- accepted.forEach((type) => {
146
- if (allow) {
147
- return;
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
- injectCssToDocument(document, css);
183
- customElements.define(FileDragElement.is, FileDragElement);
184
- return useUniDirective("file-drag-field", {
185
- mounted(el) {
186
- const input = el.querySelector("input[type=file]");
187
- const placeholderInput = el.querySelector("[data-role=placeholder]");
188
- const preview = el.querySelector(".c-file-drag-preview");
189
- if (preview) {
190
- const previewLink = preview.querySelector(".c-file-drag-preview__link");
191
- const delButton = preview.querySelector(".c-file-drag-preview__delete");
192
- let inputValue = placeholderInput.value;
193
- let required = input.required;
194
- if (placeholderInput.value) {
195
- input.required = false;
196
- }
197
- delButton.addEventListener("click", () => {
198
- if (delButton.classList.contains("active")) {
199
- previewLink.style.textDecoration = "";
200
- previewLink.style.setProperty("color", "");
201
- placeholderInput.value = inputValue;
202
- delButton.classList.remove("active");
203
- input.required = false;
204
- } else {
205
- previewLink.style.textDecoration = "line-through";
206
- previewLink.style.color = "var(--fd-delete-color, var(--bs-danger))";
207
- placeholderInput.value = "";
208
- delButton.classList.add("active");
209
- input.required = required;
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
- const ready = /* @__PURE__ */ init();
217
- export {
218
- FileDragElement,
219
- ready
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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"}