@windwalker-io/unicorn-next 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +18 -0
- package/.gulp.json +7 -0
- package/bin/release.mjs +47 -0
- package/dist/chunks/_arrayPush.js +168 -0
- package/dist/chunks/_arrayPush.js.map +1 -0
- package/dist/chunks/_baseRest.js +73 -0
- package/dist/chunks/_baseRest.js.map +1 -0
- package/dist/chunks/_commonjsHelpers.js +7 -0
- package/dist/chunks/_commonjsHelpers.js.map +1 -0
- package/dist/chunks/_getPrototype.js +130 -0
- package/dist/chunks/_getPrototype.js.map +1 -0
- package/dist/chunks/button-radio.js +147 -0
- package/dist/chunks/button-radio.js.map +1 -0
- package/dist/chunks/checkboxes-multi-select.js +44 -0
- package/dist/chunks/checkboxes-multi-select.js.map +1 -0
- package/dist/chunks/cloneDeep.js +287 -0
- package/dist/chunks/cloneDeep.js.map +1 -0
- package/dist/chunks/cropper.min.js +5 -0
- package/dist/chunks/cropper.min.js.map +1 -0
- package/dist/chunks/field-cascade-select.js +256 -0
- package/dist/chunks/field-cascade-select.js.map +1 -0
- package/dist/chunks/field-file-drag.js +218 -0
- package/dist/chunks/field-file-drag.js.map +1 -0
- package/dist/chunks/field-flatpickr.js +893 -0
- package/dist/chunks/field-flatpickr.js.map +1 -0
- package/dist/chunks/field-modal-select.js +403 -0
- package/dist/chunks/field-modal-select.js.map +1 -0
- package/dist/chunks/field-modal-tree.js +790 -0
- package/dist/chunks/field-modal-tree.js.map +1 -0
- package/dist/chunks/field-multi-uploader.js +256 -0
- package/dist/chunks/field-multi-uploader.js.map +1 -0
- package/dist/chunks/field-repeatable.js +132 -0
- package/dist/chunks/field-repeatable.js.map +1 -0
- package/dist/chunks/field-single-image-drag.js +338 -0
- package/dist/chunks/field-single-image-drag.js.map +1 -0
- package/dist/chunks/form.js +154 -0
- package/dist/chunks/form.js.map +1 -0
- package/dist/chunks/grid.js +345 -0
- package/dist/chunks/grid.js.map +1 -0
- package/dist/chunks/http-client.js +229 -0
- package/dist/chunks/http-client.js.map +1 -0
- package/dist/chunks/iframe-modal.js +124 -0
- package/dist/chunks/iframe-modal.js.map +1 -0
- package/dist/chunks/index.js +309 -0
- package/dist/chunks/index.js.map +1 -0
- package/dist/chunks/isArguments.js +146 -0
- package/dist/chunks/isArguments.js.map +1 -0
- package/dist/chunks/keep-tab.js +101 -0
- package/dist/chunks/keep-tab.js.map +1 -0
- package/dist/chunks/legacy.js +210 -0
- package/dist/chunks/legacy.js.map +1 -0
- package/dist/chunks/list-dependent.js +231 -0
- package/dist/chunks/list-dependent.js.map +1 -0
- package/dist/chunks/s3-multipart-uploader.js +172 -0
- package/dist/chunks/s3-multipart-uploader.js.map +1 -0
- package/dist/chunks/s3-uploader.js +136 -0
- package/dist/chunks/s3-uploader.js.map +1 -0
- package/dist/chunks/show-on.js +237 -0
- package/dist/chunks/show-on.js.map +1 -0
- package/dist/chunks/tinymce.js +196 -0
- package/dist/chunks/tinymce.js.map +1 -0
- package/dist/chunks/ui-bootstrap5.js +71 -0
- package/dist/chunks/ui-bootstrap5.js.map +1 -0
- package/dist/chunks/unicorn.js +2202 -0
- package/dist/chunks/unicorn.js.map +1 -0
- package/dist/chunks/validation.js +854 -0
- package/dist/chunks/validation.js.map +1 -0
- package/dist/editor.css +1 -0
- package/dist/index.d.ts +1427 -0
- package/dist/multi-level-menu.css +1 -0
- package/dist/switcher.css +1 -0
- package/dist/unicorn-next.css +12 -0
- package/dist/unicorn.js +125 -0
- package/dist/unicorn.js.map +1 -0
- package/fusionfile.mjs +155 -0
- package/images/ajax-loader.gif +0 -0
- package/images/placeholder/avatar.png +0 -0
- package/images/placeholder/image-16x10.png +0 -0
- package/images/placeholder/image-16x9.png +0 -0
- package/images/placeholder/image-1x1.png +0 -0
- package/images/placeholder/image-4x3.png +0 -0
- package/package.json +102 -0
- package/scss/bootstrap/multi-level-menu.scss +121 -0
- package/scss/editor.scss +116 -0
- package/scss/field/file-drag.scss +102 -0
- package/scss/field/single-image-drag.scss +88 -0
- package/scss/field/vue-drag-uploader.scss +160 -0
- package/scss/switcher.scss +156 -0
- package/src/app.ts +128 -0
- package/src/bootstrap/button-radio.ts +208 -0
- package/src/bootstrap/keep-tab.ts +155 -0
- package/src/composable/index.ts +21 -0
- package/src/composable/useCheckboxesMultiSelect.ts +22 -0
- package/src/composable/useFieldCascadeSelect.ts +9 -0
- package/src/composable/useFieldFileDrag.ts +9 -0
- package/src/composable/useFieldFlatpickr.ts +3 -0
- package/src/composable/useFieldModalSelect.ts +6 -0
- package/src/composable/useFieldModalTree.ts +3 -0
- package/src/composable/useFieldMultiUploader.ts +3 -0
- package/src/composable/useFieldRepeatable.ts +9 -0
- package/src/composable/useFieldSingleImageDrag.ts +5 -0
- package/src/composable/useForm.ts +43 -0
- package/src/composable/useGrid.ts +57 -0
- package/src/composable/useHttp.ts +8 -0
- package/src/composable/useIframeModal.ts +9 -0
- package/src/composable/useListDependent.ts +26 -0
- package/src/composable/useQueue.ts +13 -0
- package/src/composable/useS3Uploader.ts +32 -0
- package/src/composable/useShowOn.ts +9 -0
- package/src/composable/useStack.ts +13 -0
- package/src/composable/useTinymce.ts +29 -0
- package/src/composable/useTomSelect.ts +72 -0
- package/src/composable/useUIBootstrap5.ts +48 -0
- package/src/composable/useUniDirective.ts +32 -0
- package/src/composable/useValidation.ts +39 -0
- package/src/data.ts +36 -0
- package/src/events.ts +73 -0
- package/src/legacy/legacy.ts +186 -0
- package/src/legacy/loader.ts +125 -0
- package/src/module/checkboxes-multi-select.ts +54 -0
- package/src/module/field-cascade-select.ts +292 -0
- package/src/module/field-file-drag.ts +292 -0
- package/src/module/field-flatpickr.ts +127 -0
- package/src/module/field-modal-select.ts +174 -0
- package/src/module/field-modal-tree.ts +27 -0
- package/src/module/field-multi-uploader.ts +361 -0
- package/src/module/field-repeatable.ts +202 -0
- package/src/module/field-single-image-drag.ts +468 -0
- package/src/module/form.ts +223 -0
- package/src/module/grid.ts +465 -0
- package/src/module/http-client.ts +243 -0
- package/src/module/iframe-modal.ts +167 -0
- package/src/module/list-dependent.ts +321 -0
- package/src/module/s3-multipart-uploader.ts +300 -0
- package/src/module/s3-uploader.ts +234 -0
- package/src/module/show-on.ts +173 -0
- package/src/module/tinymce.ts +263 -0
- package/src/module/ui-bootstrap5.ts +107 -0
- package/src/module/validation.ts +1019 -0
- package/src/plugin/index.ts +1 -0
- package/src/plugin/php-adapter.ts +65 -0
- package/src/polyfill/form-request-submit.ts +31 -0
- package/src/polyfill/index.ts +9 -0
- package/src/service/animate.ts +58 -0
- package/src/service/crypto.ts +27 -0
- package/src/service/dom-watcher.ts +62 -0
- package/src/service/dom.ts +265 -0
- package/src/service/helper.ts +48 -0
- package/src/service/index.ts +10 -0
- package/src/service/lang.ts +122 -0
- package/src/service/loader.ts +152 -0
- package/src/service/router.ts +118 -0
- package/src/service/ui.ts +497 -0
- package/src/service/uri.ts +106 -0
- package/src/types/base.ts +9 -0
- package/src/types/index.ts +4 -0
- package/src/types/modal-tree.ts +12 -0
- package/src/types/plugin.ts +6 -0
- package/src/types/shims.d.ts +18 -0
- package/src/types/ui.ts +6 -0
- package/src/unicorn.ts +63 -0
- package/src/utilities/arr.ts +25 -0
- package/src/utilities/base.ts +9 -0
- package/src/utilities/data.ts +48 -0
- package/src/utilities/index.ts +5 -0
- package/src/utilities/tree.ts +20 -0
- package/src/vue/components/ModalTree/ModalTreeApp.vue +175 -0
- package/src/vue/components/ModalTree/TreeItem.vue +262 -0
- package/src/vue/components/ModalTree/TreeModal.vue +225 -0
- package/tests/test.js +4 -0
- package/tsconfig.js.json +25 -0
- package/tsconfig.json +17 -0
- package/vite.assets.config.ts +61 -0
- package/vite.config.test.ts +36 -0
- package/vite.config.ts +112 -0
|
@@ -0,0 +1,854 @@
|
|
|
1
|
+
import { a as useUniDirective, x as getBoundedInstance, v as selectOne, a5 as mergeDeep, w as selectAll, ag as trans, ah as useUITheme, B as html } from "./unicorn.js";
|
|
2
|
+
const maxInt = 2147483647;
|
|
3
|
+
const base = 36;
|
|
4
|
+
const tMin = 1;
|
|
5
|
+
const tMax = 26;
|
|
6
|
+
const skew = 38;
|
|
7
|
+
const damp = 700;
|
|
8
|
+
const initialBias = 72;
|
|
9
|
+
const initialN = 128;
|
|
10
|
+
const delimiter = "-";
|
|
11
|
+
const regexNonASCII = /[^\0-\x7F]/;
|
|
12
|
+
const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g;
|
|
13
|
+
const errors = {
|
|
14
|
+
"overflow": "Overflow: input needs wider integers to process",
|
|
15
|
+
"not-basic": "Illegal input >= 0x80 (not a basic code point)",
|
|
16
|
+
"invalid-input": "Invalid input"
|
|
17
|
+
};
|
|
18
|
+
const baseMinusTMin = base - tMin;
|
|
19
|
+
const floor = /* @__PURE__ */ (() => Math.floor)();
|
|
20
|
+
const stringFromCharCode = /* @__PURE__ */ (() => String.fromCharCode)();
|
|
21
|
+
function error(type) {
|
|
22
|
+
throw new RangeError(errors[type]);
|
|
23
|
+
}
|
|
24
|
+
function map(array, callback) {
|
|
25
|
+
const result = [];
|
|
26
|
+
let length = array.length;
|
|
27
|
+
while (length--) {
|
|
28
|
+
result[length] = callback(array[length]);
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
function mapDomain(domain, callback) {
|
|
33
|
+
const parts = domain.split("@");
|
|
34
|
+
let result = "";
|
|
35
|
+
if (parts.length > 1) {
|
|
36
|
+
result = parts[0] + "@";
|
|
37
|
+
domain = parts[1];
|
|
38
|
+
}
|
|
39
|
+
domain = domain.replace(regexSeparators, ".");
|
|
40
|
+
const labels = domain.split(".");
|
|
41
|
+
const encoded = map(labels, callback).join(".");
|
|
42
|
+
return result + encoded;
|
|
43
|
+
}
|
|
44
|
+
function ucs2decode(string) {
|
|
45
|
+
const output = [];
|
|
46
|
+
let counter = 0;
|
|
47
|
+
const length = string.length;
|
|
48
|
+
while (counter < length) {
|
|
49
|
+
const value = string.charCodeAt(counter++);
|
|
50
|
+
if (value >= 55296 && value <= 56319 && counter < length) {
|
|
51
|
+
const extra = string.charCodeAt(counter++);
|
|
52
|
+
if ((extra & 64512) == 56320) {
|
|
53
|
+
output.push(((value & 1023) << 10) + (extra & 1023) + 65536);
|
|
54
|
+
} else {
|
|
55
|
+
output.push(value);
|
|
56
|
+
counter--;
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
output.push(value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return output;
|
|
63
|
+
}
|
|
64
|
+
const digitToBasic = function(digit, flag) {
|
|
65
|
+
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
|
|
66
|
+
};
|
|
67
|
+
const adapt = function(delta, numPoints, firstTime) {
|
|
68
|
+
let k = 0;
|
|
69
|
+
delta = firstTime ? floor(delta / damp) : delta >> 1;
|
|
70
|
+
delta += floor(delta / numPoints);
|
|
71
|
+
for (; delta > baseMinusTMin * tMax >> 1; k += base) {
|
|
72
|
+
delta = floor(delta / baseMinusTMin);
|
|
73
|
+
}
|
|
74
|
+
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
|
|
75
|
+
};
|
|
76
|
+
const encode = function(input) {
|
|
77
|
+
const output = [];
|
|
78
|
+
input = ucs2decode(input);
|
|
79
|
+
const inputLength = input.length;
|
|
80
|
+
let n = initialN;
|
|
81
|
+
let delta = 0;
|
|
82
|
+
let bias = initialBias;
|
|
83
|
+
for (const currentValue of input) {
|
|
84
|
+
if (currentValue < 128) {
|
|
85
|
+
output.push(stringFromCharCode(currentValue));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const basicLength = output.length;
|
|
89
|
+
let handledCPCount = basicLength;
|
|
90
|
+
if (basicLength) {
|
|
91
|
+
output.push(delimiter);
|
|
92
|
+
}
|
|
93
|
+
while (handledCPCount < inputLength) {
|
|
94
|
+
let m = maxInt;
|
|
95
|
+
for (const currentValue of input) {
|
|
96
|
+
if (currentValue >= n && currentValue < m) {
|
|
97
|
+
m = currentValue;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const handledCPCountPlusOne = handledCPCount + 1;
|
|
101
|
+
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
|
|
102
|
+
error("overflow");
|
|
103
|
+
}
|
|
104
|
+
delta += (m - n) * handledCPCountPlusOne;
|
|
105
|
+
n = m;
|
|
106
|
+
for (const currentValue of input) {
|
|
107
|
+
if (currentValue < n && ++delta > maxInt) {
|
|
108
|
+
error("overflow");
|
|
109
|
+
}
|
|
110
|
+
if (currentValue === n) {
|
|
111
|
+
let q = delta;
|
|
112
|
+
for (let k = base; ; k += base) {
|
|
113
|
+
const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
|
|
114
|
+
if (q < t) {
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
const qMinusT = q - t;
|
|
118
|
+
const baseMinusT = base - t;
|
|
119
|
+
output.push(
|
|
120
|
+
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
|
|
121
|
+
);
|
|
122
|
+
q = floor(qMinusT / baseMinusT);
|
|
123
|
+
}
|
|
124
|
+
output.push(stringFromCharCode(digitToBasic(q, 0)));
|
|
125
|
+
bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength);
|
|
126
|
+
delta = 0;
|
|
127
|
+
++handledCPCount;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
++delta;
|
|
131
|
+
++n;
|
|
132
|
+
}
|
|
133
|
+
return output.join("");
|
|
134
|
+
};
|
|
135
|
+
const toASCII = function(input) {
|
|
136
|
+
return mapDomain(input, function(string) {
|
|
137
|
+
return regexNonASCII.test(string) ? "xn--" + encode(string) : string;
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
const validatorHandlers = {};
|
|
141
|
+
const defaultOptions = {
|
|
142
|
+
scroll: false,
|
|
143
|
+
scrollOffset: -100,
|
|
144
|
+
enabled: true,
|
|
145
|
+
fieldSelector: null,
|
|
146
|
+
validatedClass: null
|
|
147
|
+
};
|
|
148
|
+
const defaultFieldOptions = {
|
|
149
|
+
formSelector: "[uni-form-validate]",
|
|
150
|
+
errorSelector: "[data-field-error]",
|
|
151
|
+
selector: "input[data-field-input], select[data-field-input], textarea[data-field-input]",
|
|
152
|
+
validClass: "is-valid",
|
|
153
|
+
invalidClass: "is-invalid",
|
|
154
|
+
events: ["change"],
|
|
155
|
+
errorMessageClass: "invalid-tooltip",
|
|
156
|
+
inputOptions: false,
|
|
157
|
+
inputOptionsWrapperSelector: "div[data-field-input]",
|
|
158
|
+
inputOptionsSelector: "[data-input-option]"
|
|
159
|
+
};
|
|
160
|
+
class UnicornFormValidation {
|
|
161
|
+
presetFields = [];
|
|
162
|
+
static globalValidators = {};
|
|
163
|
+
validators = {};
|
|
164
|
+
options;
|
|
165
|
+
$form;
|
|
166
|
+
static is = "uni-form-validate";
|
|
167
|
+
constructor(el, options = {}) {
|
|
168
|
+
this.$form = selectOne(el);
|
|
169
|
+
this.options = this.mergeOptions(options);
|
|
170
|
+
this.registerDefaultValidators();
|
|
171
|
+
this.init();
|
|
172
|
+
}
|
|
173
|
+
mergeOptions(options) {
|
|
174
|
+
if (Array.isArray(options)) {
|
|
175
|
+
options = {};
|
|
176
|
+
}
|
|
177
|
+
return this.options = mergeDeep({}, defaultOptions, options);
|
|
178
|
+
}
|
|
179
|
+
get scrollEnabled() {
|
|
180
|
+
return this.options.scroll;
|
|
181
|
+
}
|
|
182
|
+
get scrollOffset() {
|
|
183
|
+
return Number(this.options.scrollOffset || -100);
|
|
184
|
+
}
|
|
185
|
+
get fieldSelector() {
|
|
186
|
+
return this.options.fieldSelector || "input, select, textarea";
|
|
187
|
+
}
|
|
188
|
+
get validatedClass() {
|
|
189
|
+
return this.options.validatedClass || "was-validated";
|
|
190
|
+
}
|
|
191
|
+
init() {
|
|
192
|
+
if (this.$form.tagName === "FORM") {
|
|
193
|
+
this.$form.setAttribute("novalidate", "true");
|
|
194
|
+
this.$form.addEventListener("submit", (event) => {
|
|
195
|
+
if (this.options.enabled && !this.validateAll()) {
|
|
196
|
+
event.stopImmediatePropagation();
|
|
197
|
+
event.stopPropagation();
|
|
198
|
+
event.preventDefault();
|
|
199
|
+
this.$form.dispatchEvent(new CustomEvent("invalid"));
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
}, false);
|
|
204
|
+
}
|
|
205
|
+
this.prepareFields(this.findDOMFields());
|
|
206
|
+
this.prepareFields(this.presetFields);
|
|
207
|
+
}
|
|
208
|
+
findDOMFields() {
|
|
209
|
+
return selectAll(this.$form.querySelectorAll(this.fieldSelector));
|
|
210
|
+
}
|
|
211
|
+
prepareFields(inputs) {
|
|
212
|
+
inputs.forEach((input) => {
|
|
213
|
+
this.prepareFieldWrapper(input);
|
|
214
|
+
});
|
|
215
|
+
return Promise.resolve();
|
|
216
|
+
}
|
|
217
|
+
prepareFieldWrapper(input) {
|
|
218
|
+
if (["INPUT", "SELECT", "TEXTAREA"].indexOf(input.tagName) !== -1) {
|
|
219
|
+
let wrapper = input.closest("[uni-field-validate]");
|
|
220
|
+
if (!wrapper) {
|
|
221
|
+
wrapper = input.closest("[data-input-container]") || input.parentElement;
|
|
222
|
+
wrapper?.setAttribute("uni-field-validate", "{}");
|
|
223
|
+
}
|
|
224
|
+
return wrapper;
|
|
225
|
+
}
|
|
226
|
+
return input;
|
|
227
|
+
}
|
|
228
|
+
findFields(containsPresets = true) {
|
|
229
|
+
let inputs = this.findDOMFields();
|
|
230
|
+
if (containsPresets) {
|
|
231
|
+
inputs.push(...this.presetFields);
|
|
232
|
+
}
|
|
233
|
+
return inputs.map((input) => this.prepareFieldWrapper(input)).filter((input) => input != null);
|
|
234
|
+
}
|
|
235
|
+
getFieldComponent(input) {
|
|
236
|
+
let v = getBoundedInstance(input, "field.validation");
|
|
237
|
+
if (!v) {
|
|
238
|
+
const wrapper = input.closest("[uni-field-validate]");
|
|
239
|
+
if (wrapper) {
|
|
240
|
+
v = getBoundedInstance(wrapper, "field.validation");
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return v;
|
|
244
|
+
}
|
|
245
|
+
validateAll(fields) {
|
|
246
|
+
this.markFormAsUnvalidated();
|
|
247
|
+
fields = fields || this.findFields();
|
|
248
|
+
let firstFail = null;
|
|
249
|
+
for (const field of fields) {
|
|
250
|
+
const fv = this.getFieldComponent(field);
|
|
251
|
+
if (!fv) {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const result = fv.checkValidity();
|
|
255
|
+
if (!result && !firstFail) {
|
|
256
|
+
firstFail = field;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
this.markFormAsValidated();
|
|
260
|
+
if (firstFail && this.scrollEnabled) {
|
|
261
|
+
this.scrollTo(firstFail);
|
|
262
|
+
}
|
|
263
|
+
return firstFail === null;
|
|
264
|
+
}
|
|
265
|
+
async validateAllAsync(fields) {
|
|
266
|
+
this.markFormAsUnvalidated();
|
|
267
|
+
fields = fields || this.findFields();
|
|
268
|
+
let firstFail = null;
|
|
269
|
+
const promises = [];
|
|
270
|
+
for (const field of fields) {
|
|
271
|
+
const fv = this.getFieldComponent(field);
|
|
272
|
+
if (!fv) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
promises.push(
|
|
276
|
+
fv.checkValidityAsync().then((result) => {
|
|
277
|
+
if (!result && !firstFail) {
|
|
278
|
+
firstFail = field;
|
|
279
|
+
}
|
|
280
|
+
return result;
|
|
281
|
+
})
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
await Promise.all(promises);
|
|
285
|
+
this.markFormAsValidated();
|
|
286
|
+
if (firstFail && this.scrollEnabled) {
|
|
287
|
+
this.scrollTo(firstFail);
|
|
288
|
+
}
|
|
289
|
+
return firstFail === null;
|
|
290
|
+
}
|
|
291
|
+
scrollTo(element) {
|
|
292
|
+
const offset = this.scrollOffset;
|
|
293
|
+
const elementPosition = element.getBoundingClientRect().top;
|
|
294
|
+
const offsetPosition = elementPosition + window.scrollY + offset;
|
|
295
|
+
window.scrollTo({
|
|
296
|
+
top: offsetPosition,
|
|
297
|
+
behavior: "smooth"
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
markFormAsValidated() {
|
|
301
|
+
if (!this.$form) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
this.$form.classList.add(this.validatedClass);
|
|
305
|
+
}
|
|
306
|
+
markFormAsUnvalidated() {
|
|
307
|
+
if (!this.$form) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
this.$form.classList.remove(this.validatedClass);
|
|
311
|
+
}
|
|
312
|
+
addField(field) {
|
|
313
|
+
this.presetFields.push(field);
|
|
314
|
+
this.prepareFieldWrapper(field);
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
registerDefaultValidators() {
|
|
318
|
+
for (let name in validatorHandlers) {
|
|
319
|
+
this.addValidator(name, validatorHandlers[name]);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Add validator handler.
|
|
324
|
+
*/
|
|
325
|
+
addValidator(name, handler, options = {}) {
|
|
326
|
+
options = options || {};
|
|
327
|
+
this.validators[name] = {
|
|
328
|
+
handler,
|
|
329
|
+
options
|
|
330
|
+
};
|
|
331
|
+
return this;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Add validator handler.
|
|
335
|
+
*/
|
|
336
|
+
static addGlobalValidator(name, handler, options = {}) {
|
|
337
|
+
options = options || {};
|
|
338
|
+
this.globalValidators[name] = {
|
|
339
|
+
handler,
|
|
340
|
+
options
|
|
341
|
+
};
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
class UnicornFieldValidation {
|
|
346
|
+
constructor(el, options = {}) {
|
|
347
|
+
this.el = el;
|
|
348
|
+
this.options = this.mergeOptions(options);
|
|
349
|
+
this.$input = this.selectInput();
|
|
350
|
+
this.init();
|
|
351
|
+
}
|
|
352
|
+
$input;
|
|
353
|
+
options;
|
|
354
|
+
static is = "uni-field-validate";
|
|
355
|
+
mergeOptions(options) {
|
|
356
|
+
if (Array.isArray(options)) {
|
|
357
|
+
options = {};
|
|
358
|
+
}
|
|
359
|
+
return this.options = mergeDeep({}, defaultFieldOptions, options);
|
|
360
|
+
}
|
|
361
|
+
get $form() {
|
|
362
|
+
return this.getForm();
|
|
363
|
+
}
|
|
364
|
+
get errorSelector() {
|
|
365
|
+
return this.options.errorSelector;
|
|
366
|
+
}
|
|
367
|
+
get selector() {
|
|
368
|
+
return this.options.selector;
|
|
369
|
+
}
|
|
370
|
+
get validClass() {
|
|
371
|
+
return this.options.validClass;
|
|
372
|
+
}
|
|
373
|
+
get invalidClass() {
|
|
374
|
+
return this.options.invalidClass;
|
|
375
|
+
}
|
|
376
|
+
get isVisible() {
|
|
377
|
+
return !!(this.el.offsetWidth || this.el.offsetHeight || this.el.getClientRects().length);
|
|
378
|
+
}
|
|
379
|
+
get isInputOptions() {
|
|
380
|
+
return Boolean(this.options.inputOptions);
|
|
381
|
+
}
|
|
382
|
+
get validationMessage() {
|
|
383
|
+
return this.$input?.validationMessage || "";
|
|
384
|
+
}
|
|
385
|
+
get validity() {
|
|
386
|
+
return this.$input?.validity;
|
|
387
|
+
}
|
|
388
|
+
selectInput() {
|
|
389
|
+
let selector = this.selector;
|
|
390
|
+
if (this.options.inputOptions) {
|
|
391
|
+
selector += ", " + this.options.inputOptionsWrapperSelector;
|
|
392
|
+
}
|
|
393
|
+
let input = this.el.querySelector(selector);
|
|
394
|
+
if (!input) {
|
|
395
|
+
input = this.el.querySelector("input, select, textarea");
|
|
396
|
+
}
|
|
397
|
+
if (!input) {
|
|
398
|
+
return void 0;
|
|
399
|
+
}
|
|
400
|
+
return this.$input = input;
|
|
401
|
+
}
|
|
402
|
+
init() {
|
|
403
|
+
this.selectInput();
|
|
404
|
+
this.bindEvents();
|
|
405
|
+
this.prepareWrapper();
|
|
406
|
+
if (this.isInputOptions) {
|
|
407
|
+
const $input = this.$input;
|
|
408
|
+
$input.validationMessage = "";
|
|
409
|
+
$input.setCustomValidity = (msg) => {
|
|
410
|
+
$input.validationMessage = String(msg);
|
|
411
|
+
};
|
|
412
|
+
$input.checkValidity = () => {
|
|
413
|
+
return this.checkInputOptionsValidity();
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
bindEvents() {
|
|
418
|
+
if (!this.$input) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.$input.addEventListener("invalid", (e) => {
|
|
422
|
+
this.showInvalidResponse();
|
|
423
|
+
});
|
|
424
|
+
const events = this.options.events;
|
|
425
|
+
events.forEach((eventName) => {
|
|
426
|
+
this.$input?.addEventListener(eventName, () => {
|
|
427
|
+
this.checkValidity();
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
prepareWrapper() {
|
|
432
|
+
if (this.el.querySelector(this.errorSelector)?.classList?.contains("invalid-tooltip")) {
|
|
433
|
+
if (window.getComputedStyle(this.el).position === "static") {
|
|
434
|
+
this.el.style.position = "relative";
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
checkValidity() {
|
|
439
|
+
if (!this.$input) {
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
if (this.$input.hasAttribute("readonly")) {
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
if (this.$input.hasAttribute("[data-novalidate]")) {
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
if (this.$input.closest("[data-novalidate]")) {
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
this.$input.setCustomValidity("");
|
|
452
|
+
let valid = this.$input.checkValidity();
|
|
453
|
+
if (valid && this.$form) {
|
|
454
|
+
valid = this.runCustomValidity();
|
|
455
|
+
}
|
|
456
|
+
this.updateValidClass(valid);
|
|
457
|
+
return valid;
|
|
458
|
+
}
|
|
459
|
+
runCustomValidity() {
|
|
460
|
+
if (!this.$input) {
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
463
|
+
const validates = (this.$input.getAttribute("data-validate") || "").split("|");
|
|
464
|
+
let result = true;
|
|
465
|
+
if (this.$input.value !== "" && validates.length) {
|
|
466
|
+
if (!this.checkCustomDataAttributeValidity()) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
for (const validatorName of validates) {
|
|
470
|
+
const [validator, options] = this.getValidator(validatorName) || [null, {}];
|
|
471
|
+
if (!validator) {
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
Object.assign(options, validator.options);
|
|
475
|
+
let r = validator.handler(this.$input.value, this.$input, options, this);
|
|
476
|
+
if (r instanceof Promise || typeof r === "object" && r.then) {
|
|
477
|
+
r.then((result2) => {
|
|
478
|
+
this.handleAsyncCustomResult(result2, validator);
|
|
479
|
+
});
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
if (!this.handleCustomResult(r, validator)) {
|
|
483
|
+
result = false;
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return result;
|
|
489
|
+
}
|
|
490
|
+
async checkValidityAsync() {
|
|
491
|
+
if (!this.$input) {
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
if (this.$input.hasAttribute("readonly")) {
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
497
|
+
this.$input.setCustomValidity("");
|
|
498
|
+
let valid = this.$input.checkValidity();
|
|
499
|
+
if (valid && this.$form) {
|
|
500
|
+
valid = await this.runCustomValidityAsync();
|
|
501
|
+
}
|
|
502
|
+
this.updateValidClass(valid);
|
|
503
|
+
return valid;
|
|
504
|
+
}
|
|
505
|
+
async runCustomValidityAsync() {
|
|
506
|
+
if (!this.$input) {
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
const validates = (this.$input.getAttribute("data-validate") || "").split("|");
|
|
510
|
+
const results = [];
|
|
511
|
+
const promises = [];
|
|
512
|
+
if (this.$input.value !== "" && validates.length) {
|
|
513
|
+
if (!this.checkCustomDataAttributeValidity()) {
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
for (const validatorName of validates) {
|
|
517
|
+
let [validator, options] = this.getValidator(validatorName) || [null, {}];
|
|
518
|
+
if (!validator) {
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
options = Object.assign({}, options, validator.options || {});
|
|
522
|
+
promises.push(
|
|
523
|
+
Promise.resolve(validator.handler(this.$input.value, this.$input, options, this)).then((r) => {
|
|
524
|
+
results.push(this.handleAsyncCustomResult(r, validator));
|
|
525
|
+
return r;
|
|
526
|
+
})
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
await Promise.all(promises);
|
|
531
|
+
for (const result of results) {
|
|
532
|
+
if (result === false) {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
checkCustomDataAttributeValidity() {
|
|
539
|
+
const error2 = this.$input?.dataset.validationFail;
|
|
540
|
+
return this.handleCustomResult(error2);
|
|
541
|
+
}
|
|
542
|
+
checkInputOptionsValidity() {
|
|
543
|
+
if (!this.$input) {
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
const isRequired = this.$input.getAttribute("required") != null;
|
|
547
|
+
const optionWrappers = this.$input.querySelectorAll(this.options.inputOptionsSelector);
|
|
548
|
+
let result = true;
|
|
549
|
+
if (isRequired) {
|
|
550
|
+
for (const optionWrapper of optionWrappers) {
|
|
551
|
+
const input = optionWrapper.querySelector("input");
|
|
552
|
+
result = false;
|
|
553
|
+
if (input?.checked) {
|
|
554
|
+
result = true;
|
|
555
|
+
break;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
const n = document.createElement("input");
|
|
560
|
+
n.required = isRequired;
|
|
561
|
+
if (result) {
|
|
562
|
+
n.value = "placeholder";
|
|
563
|
+
}
|
|
564
|
+
n.checkValidity();
|
|
565
|
+
this.$input.validationMessage = n.validationMessage;
|
|
566
|
+
this.$input.validity = n.validity;
|
|
567
|
+
for (const optionWrapper of optionWrappers) {
|
|
568
|
+
const input = optionWrapper.querySelector("input");
|
|
569
|
+
input?.setCustomValidity(n.validationMessage);
|
|
570
|
+
}
|
|
571
|
+
if (!result) {
|
|
572
|
+
this.$input.dispatchEvent(
|
|
573
|
+
new CustomEvent("invalid")
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
return result;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* @param valid {boolean}
|
|
580
|
+
*/
|
|
581
|
+
updateValidClass(valid) {
|
|
582
|
+
const $errorElement = this.getErrorElement();
|
|
583
|
+
const $invalidTarget = $errorElement?.previousElementSibling;
|
|
584
|
+
this.$input?.classList.remove(this.invalidClass);
|
|
585
|
+
this.$input?.classList.remove(this.validClass);
|
|
586
|
+
this.el.classList.remove(this.invalidClass);
|
|
587
|
+
this.el.classList.remove(this.validClass);
|
|
588
|
+
$invalidTarget?.classList.remove(this.invalidClass);
|
|
589
|
+
$invalidTarget?.classList.remove(this.validClass);
|
|
590
|
+
if (valid) {
|
|
591
|
+
this.$input?.classList.add(this.validClass);
|
|
592
|
+
this.el.classList.add(this.validClass);
|
|
593
|
+
$invalidTarget?.classList.add(this.validClass);
|
|
594
|
+
} else {
|
|
595
|
+
this.$input?.classList.add(this.invalidClass);
|
|
596
|
+
this.el.classList.add(this.invalidClass);
|
|
597
|
+
$invalidTarget?.classList.add(this.invalidClass);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
getFormValidation(element) {
|
|
601
|
+
return getBoundedInstance(element || this.getForm(), "form.validation");
|
|
602
|
+
}
|
|
603
|
+
getValidator(name) {
|
|
604
|
+
const matches = name.match(/(?<type>[\w\-_]+)(\((?<params>.*)\))*/);
|
|
605
|
+
if (!matches) {
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
const validatorName = matches.groups?.type || "";
|
|
609
|
+
const params = matches.groups?.params || "";
|
|
610
|
+
const fv = this.getFormValidation(this.$form);
|
|
611
|
+
const validator = fv?.validators[validatorName] || UnicornFormValidation.globalValidators[validatorName];
|
|
612
|
+
if (!validator) {
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
const paramMatches = params.matchAll(/(?<key>\w+)(\s?[=:]\s?(?<value>\w+))?/g);
|
|
616
|
+
const options = {};
|
|
617
|
+
for (const paramMatch of paramMatches) {
|
|
618
|
+
const match = paramMatch?.groups;
|
|
619
|
+
if (!match) {
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
options[match.key] = handleParamValue(match.value);
|
|
623
|
+
}
|
|
624
|
+
return [validator, options];
|
|
625
|
+
}
|
|
626
|
+
handleCustomResult(result, validator) {
|
|
627
|
+
if (typeof result === "string") {
|
|
628
|
+
this.$input?.setCustomValidity(result);
|
|
629
|
+
result = result === "";
|
|
630
|
+
} else if (result === void 0) {
|
|
631
|
+
result = true;
|
|
632
|
+
}
|
|
633
|
+
if (result) {
|
|
634
|
+
this.$input?.setCustomValidity("");
|
|
635
|
+
} else if (validator) {
|
|
636
|
+
this.raiseCustomErrorState(validator);
|
|
637
|
+
}
|
|
638
|
+
return result;
|
|
639
|
+
}
|
|
640
|
+
handleAsyncCustomResult(result, validator) {
|
|
641
|
+
result = this.handleCustomResult(result, validator);
|
|
642
|
+
this.$input?.checkValidity();
|
|
643
|
+
this.updateValidClass(result);
|
|
644
|
+
return result;
|
|
645
|
+
}
|
|
646
|
+
raiseCustomErrorState(validator) {
|
|
647
|
+
let help;
|
|
648
|
+
if (this.$input?.validationMessage === "") {
|
|
649
|
+
help = validator.options?.notice;
|
|
650
|
+
if (typeof help === "function") {
|
|
651
|
+
help = help(this.$input, this);
|
|
652
|
+
}
|
|
653
|
+
if (help != null) {
|
|
654
|
+
this.$input?.setCustomValidity(help);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
if (this.$input?.validationMessage === "") {
|
|
658
|
+
this.$input?.setCustomValidity(trans("unicorn.message.validation.custom.error"));
|
|
659
|
+
}
|
|
660
|
+
this.$input?.dispatchEvent(
|
|
661
|
+
new CustomEvent("invalid")
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
setAsInvalidAndReport(error2) {
|
|
665
|
+
this.setCustomValidity(error2);
|
|
666
|
+
this.showInvalidResponse();
|
|
667
|
+
}
|
|
668
|
+
setCustomValidity(error2) {
|
|
669
|
+
this.$input?.setCustomValidity(error2);
|
|
670
|
+
}
|
|
671
|
+
reportValidity() {
|
|
672
|
+
if (this.validationMessage !== "") {
|
|
673
|
+
this.showInvalidResponse();
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
showInvalidResponse() {
|
|
677
|
+
const state = this.$input?.validity;
|
|
678
|
+
let message = this.$input?.validationMessage || "";
|
|
679
|
+
for (let key in state) {
|
|
680
|
+
if (state[key] && this.$input?.dataset[key + "Message"]) {
|
|
681
|
+
message = this.$input?.dataset[key + "Message"] || "";
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
if (!this.isVisible) {
|
|
686
|
+
let title = this.findLabel()?.textContent;
|
|
687
|
+
if (!title) {
|
|
688
|
+
title = this.$input?.name || "";
|
|
689
|
+
}
|
|
690
|
+
useUITheme().renderMessage(
|
|
691
|
+
`Field: ${title} - ${message}`,
|
|
692
|
+
"warning"
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
let $help = this.getErrorElement();
|
|
696
|
+
if (!$help) {
|
|
697
|
+
$help = this.createHelpElement();
|
|
698
|
+
this.el.appendChild($help);
|
|
699
|
+
this.prepareWrapper();
|
|
700
|
+
}
|
|
701
|
+
$help.textContent = message;
|
|
702
|
+
this.updateValidClass(false);
|
|
703
|
+
}
|
|
704
|
+
getErrorElement() {
|
|
705
|
+
return this.el.querySelector(this.errorSelector);
|
|
706
|
+
}
|
|
707
|
+
createHelpElement() {
|
|
708
|
+
const className = this.options.errorMessageClass;
|
|
709
|
+
const parsed = this.parseSelector(this.errorSelector || "");
|
|
710
|
+
const $help = html(`<div class="${className}"></div>`);
|
|
711
|
+
$help.classList.add(...parsed.classes);
|
|
712
|
+
parsed.attrs.forEach((attr) => {
|
|
713
|
+
$help.setAttribute(attr[0], attr[1] || "");
|
|
714
|
+
});
|
|
715
|
+
parsed.ids.forEach((id) => {
|
|
716
|
+
$help.id = id;
|
|
717
|
+
});
|
|
718
|
+
return $help;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* @see https://stackoverflow.com/a/17888178
|
|
722
|
+
*/
|
|
723
|
+
parseSelector(subselector) {
|
|
724
|
+
const obj = { tags: [], classes: [], ids: [], attrs: [] };
|
|
725
|
+
for (const token of subselector.split(/(?=\.)|(?=#)|(?=\[)/)) {
|
|
726
|
+
switch (token[0]) {
|
|
727
|
+
case "#":
|
|
728
|
+
obj.ids.push(token.slice(1));
|
|
729
|
+
break;
|
|
730
|
+
case ".":
|
|
731
|
+
obj.classes.push(token.slice(1));
|
|
732
|
+
break;
|
|
733
|
+
case "[":
|
|
734
|
+
obj.attrs.push(token.slice(1, -1).split("="));
|
|
735
|
+
break;
|
|
736
|
+
default:
|
|
737
|
+
obj.tags.push(token);
|
|
738
|
+
break;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return obj;
|
|
742
|
+
}
|
|
743
|
+
setAsValidAndClearResponse() {
|
|
744
|
+
this.setCustomValidity("");
|
|
745
|
+
this.updateValidClass(true);
|
|
746
|
+
this.clearInvalidResponse();
|
|
747
|
+
}
|
|
748
|
+
clearInvalidResponse() {
|
|
749
|
+
const $help = this.el.querySelector(this.errorSelector);
|
|
750
|
+
$help.textContent = "";
|
|
751
|
+
}
|
|
752
|
+
getForm() {
|
|
753
|
+
return this.el.closest(this.options.formSelector || "[uni-form-validate]");
|
|
754
|
+
}
|
|
755
|
+
findLabel() {
|
|
756
|
+
const id = this.$input?.id || "";
|
|
757
|
+
const wrapper = this.$input?.closest("[data-field-wrapper]");
|
|
758
|
+
let label = null;
|
|
759
|
+
if (wrapper) {
|
|
760
|
+
label = wrapper.querySelector("[data-field-label]");
|
|
761
|
+
}
|
|
762
|
+
if (!label) {
|
|
763
|
+
label = document.querySelector(`label[for="${id}"]`);
|
|
764
|
+
}
|
|
765
|
+
return label;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
validatorHandlers.username = function(value, element) {
|
|
769
|
+
const regex = new RegExp(`[<|>|"|'|%|;|(|)|&]`, "i");
|
|
770
|
+
return !regex.test(value);
|
|
771
|
+
};
|
|
772
|
+
validatorHandlers.numeric = function(value, element) {
|
|
773
|
+
const regex = /^(\d|-)?(\d|,)*\.?\d*$/;
|
|
774
|
+
return regex.test(value);
|
|
775
|
+
};
|
|
776
|
+
validatorHandlers.email = function(value, element) {
|
|
777
|
+
value = toASCII(value);
|
|
778
|
+
const regex = /^[a-zA-Z0-9.!#$%&’*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
|
|
779
|
+
return regex.test(value);
|
|
780
|
+
};
|
|
781
|
+
validatorHandlers.url = function(value, element) {
|
|
782
|
+
const regex = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i;
|
|
783
|
+
return regex.test(value);
|
|
784
|
+
};
|
|
785
|
+
validatorHandlers.alnum = function(value, element) {
|
|
786
|
+
const regex = /^[a-zA-Z0-9]*$/;
|
|
787
|
+
return regex.test(value);
|
|
788
|
+
};
|
|
789
|
+
validatorHandlers.color = function(value, element) {
|
|
790
|
+
const regex = /^#(?:[0-9a-f]{3}){1,2}$/;
|
|
791
|
+
return regex.test(value);
|
|
792
|
+
};
|
|
793
|
+
validatorHandlers.creditcard = function(value, element) {
|
|
794
|
+
const regex = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|622((12[6-9]|1[3-9][0-9])|([2-8][0-9][0-9])|(9(([0-1][0-9])|(2[0-5]))))[0-9]{10}|64[4-9][0-9]{13}|65[0-9]{14}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})*$/;
|
|
795
|
+
return regex.test(value);
|
|
796
|
+
};
|
|
797
|
+
validatorHandlers.ip = function(value, element) {
|
|
798
|
+
const regex = /^((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))*$/;
|
|
799
|
+
return regex.test(value);
|
|
800
|
+
};
|
|
801
|
+
validatorHandlers["password-confirm"] = function(value, element) {
|
|
802
|
+
const selector = element.dataset.confirmTarget;
|
|
803
|
+
if (!selector) {
|
|
804
|
+
throw new Error('Validator: "password-confirm" must add "data-confirm-target" attribute.');
|
|
805
|
+
}
|
|
806
|
+
const target = document.querySelector(selector);
|
|
807
|
+
return target?.value === value;
|
|
808
|
+
};
|
|
809
|
+
const ready = /* @__PURE__ */ Promise.all([
|
|
810
|
+
/* @__PURE__ */ useUniDirective("form-validate", {
|
|
811
|
+
mounted(el, binding) {
|
|
812
|
+
getBoundedInstance(el, "form.validation", (ele) => {
|
|
813
|
+
return new UnicornFormValidation(ele, JSON.parse(binding.value || "{}"));
|
|
814
|
+
});
|
|
815
|
+
},
|
|
816
|
+
updated(el, binding) {
|
|
817
|
+
const instance = getBoundedInstance(el, "form.validation");
|
|
818
|
+
instance.mergeOptions(JSON.parse(binding.value || "{}"));
|
|
819
|
+
}
|
|
820
|
+
}),
|
|
821
|
+
/* @__PURE__ */ useUniDirective("field-validate", {
|
|
822
|
+
mounted(el, binding) {
|
|
823
|
+
getBoundedInstance(el, "field.validation", (ele) => {
|
|
824
|
+
return new UnicornFieldValidation(ele, JSON.parse(binding.value || "{}"));
|
|
825
|
+
});
|
|
826
|
+
},
|
|
827
|
+
updated(el, binding) {
|
|
828
|
+
const instance = getBoundedInstance(el, "field.validation");
|
|
829
|
+
instance.mergeOptions(JSON.parse(binding.value || "{}") || {});
|
|
830
|
+
}
|
|
831
|
+
})
|
|
832
|
+
]);
|
|
833
|
+
function handleParamValue(value) {
|
|
834
|
+
if (!isNaN(Number(value))) {
|
|
835
|
+
return Number(value);
|
|
836
|
+
}
|
|
837
|
+
if (value === "null") {
|
|
838
|
+
return null;
|
|
839
|
+
}
|
|
840
|
+
if (value === "true") {
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
843
|
+
if (value === "false") {
|
|
844
|
+
return true;
|
|
845
|
+
}
|
|
846
|
+
return value;
|
|
847
|
+
}
|
|
848
|
+
export {
|
|
849
|
+
UnicornFieldValidation,
|
|
850
|
+
UnicornFormValidation,
|
|
851
|
+
ready,
|
|
852
|
+
validatorHandlers as validators
|
|
853
|
+
};
|
|
854
|
+
//# sourceMappingURL=validation.js.map
|