vue-dog-form
Version:
The simplest vue 3 form validation plugin.
336 lines (335 loc) • 9.93 kB
JavaScript
import { defineComponent as z, provide as _, inject as h, ref as E, onBeforeMount as M, watch as b, openBlock as A, createElementBlock as w, withModifiers as k, renderSlot as R, onMounted as q, useAttrs as B, onBeforeUnmount as F, normalizeClass as S, toDisplayString as D, createCommentVNode as L } from "vue";
const C = {
required: {
rule(t, e) {
if (t == null || t == null)
return {
type: "required"
};
if (Array.isArray(t) || typeof t == "string" || t instanceof FileList) {
if (t.length < 1)
return {
type: "required"
};
} else if (typeof t == "number" && isNaN(t))
return {
type: "required"
};
},
message: "This field is required."
},
minlength: {
rule(t, e) {
if (t.length < parseInt(e))
return {
type: "minlength",
value: {
n: e
}
};
},
message: "Input must be at least {n} characters."
},
maxlength: {
rule(t, e) {
if (t.length > parseInt(e))
return {
type: "maxlength",
value: {
n: e
}
};
},
message: "Input cannot be more than {n} characters."
},
equalto: {
rule(t, e) {
if (t != e)
return {
type: "equalto"
};
},
message: "Input value does not match.",
auto: !0
},
notequalto: {
rule(t, e) {
if (t == e)
return {
type: "notequalto"
};
},
message: "Input value cannot be the same.",
auto: !0
},
validemail: {
rule(t, e) {
const a = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?: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]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
if (!t.match(a))
return {
type: "validemail"
};
},
message: "Please enter a valid email."
},
min: {
rule(t, e) {
if (t < parseFloat(e))
return {
type: "min",
value: {
n: e
}
};
},
message: "Minimum value is {n}."
},
max: {
rule(t, e) {
if (t > parseFloat(e))
return {
type: "max",
value: {
n: e
}
};
},
message: "Maximum value is {n}."
},
accept: {
rule(t, e) {
const a = e.trim().split(",");
let r = [], f = [];
a.forEach((l, i) => {
if (l.indexOf("/") > -1)
r.push(l);
else {
let u = l.match(/\.\w{1,}$/);
u && u[0] && f.push(u[0]);
}
});
let n = [];
const m = t;
for (let l = 0; l < m.length; l++) {
let i = !1, u = !1, g = m[l].name.match(/\.\w{1,}$/)[0], y = m[l].type.substr(0, m[l].type.indexOf("/"));
for (let v = 0; v < r.length; v++)
if (r[v].indexOf(y) > -1) {
if (r[v].indexOf("/*") > -1) {
i = !0;
break;
} else if (r[v].indexOf(m[l].type) > -1) {
i = !0;
break;
}
}
i || f.indexOf(g) > -1 && (u = !0), !i && !u && n.push(l);
}
if (n.length > 0)
return {
invalidFiles: n,
type: "accept"
};
},
message: "File(s) extension is not accepted."
},
maxfile: {
rule(t, e) {
if (t.length > parseInt(e))
return {
type: "maxfile",
value: {
n: e
}
};
},
message: "Please select not more than {n} files."
},
maxsize: {
rule(t, e) {
let a = [];
for (let r = 0; r < t.length; r++)
t[r].size > parseInt(e) && a.push(r);
if (a.length > 0) {
const r = parseInt(e) / 1024 / 1024;
return {
isValid: !1,
invalidFiles: a,
type: "maxsize",
value: {
n: r.toString()
}
};
}
},
message: "File(s) must less than {n}Mb."
}
}, V = Symbol(), I = Symbol(), O = Symbol(), N = ["novalidate"], j = /* @__PURE__ */ z({
inheritAttrs: !1,
__name: "DForm",
props: {
nativeValidate: { type: Boolean, default: void 0 },
focusError: { type: Boolean, default: !1 },
focusOffset: { default: 0 },
activate: {}
},
emits: ["submit"],
setup(t, { expose: e, emit: a }) {
const r = t, f = a;
let n = [];
_(I, n);
const m = () => {
n.forEach((s) => {
s.clear();
});
}, l = h(V), i = E(!0);
_(O, i);
const u = () => {
let s = typeof r.activate == "string" ? r.activate : (l == null ? void 0 : l.activate) || "always";
!s || s == "first_submit" || s == "only_submit" || s == "never" ? (i.value = !1, m()) : i.value = !0;
};
M(() => {
u();
}), b(() => r.activate, () => {
u();
});
const g = E(!1), y = () => {
if (typeof r.nativeValidate == "boolean") {
g.value = r.nativeValidate;
return;
} else typeof (l == null ? void 0 : l.nativeValidate) == "boolean" ? g.value = l.nativeValidate : g.value = !1;
};
M(() => {
y();
}), b(() => r.nativeValidate, () => {
y();
});
const v = (s) => {
if (!i.value) {
if (r.activate == "never") {
s.isValid = !0, f("submit", s);
return;
}
i.value = !0;
}
let o = 0, c = null;
if (n.forEach((p) => {
let x = p.validate();
x != null && x.type && (o++, !c && x.errorElements && x.errorElements.length > 0 && (c = x.errorElements[0]));
}), s.isValid = o < 1, r.focusError && c) {
const p = c.getBoundingClientRect().top, x = r.focusOffset || 0;
window.scrollTo({
top: p + window.scrollY - x,
behavior: "smooth"
});
}
f("submit", s), r.activate == "only_submit" && (i.value = !1);
};
return e({
clearErrors: m,
hasError: () => {
let s = !1;
for (let o = 0; o < n.length; o++)
if (n[o].errorMessage.value) {
s = !0;
break;
}
return s;
}
}), (s, o) => (A(), w("form", {
onSubmit: k(v, ["prevent"]),
class: "_dog-form",
novalidate: !g.value
}, [
R(s.$slots, "default")
], 40, N));
}
}), K = /* @__PURE__ */ z({
__name: "DError",
props: {
modelValue: {},
messages: {},
target: {}
},
setup(t, { expose: e }) {
const a = t, r = Math.random().toString(), f = h(I);
q(() => {
f == null || f.push({
id: r,
validate: y,
clear: v,
errorMessage: i
});
});
const n = B(), m = () => a.modelValue == null || a.modelValue == null ? !1 : !((typeof a.modelValue == "string" || Array.isArray(a.modelValue)) && a.modelValue.length == 0), l = () => !(!("required" in n) || typeof n.required == "boolean" && !n.required), i = E(""), u = h(V), g = h(O), y = (d) => {
if (!d && (!g || !g.value))
return;
i.value = "";
let s = [];
if (a.target && (s = document.querySelectorAll(a.target), s.forEach((c) => c.classList.remove("invalid", "valid"))), !m() && !l())
return;
let o = {};
for (let c in n) {
let p = n[c];
if (u != null && u.validationRules[c] && (o = u.validationRules[c].rule(a.modelValue, p), o && o.type)) {
a.messages && typeof a.messages[o.type] == "string" ? i.value = a.messages[o.type] : i.value = u.message(o);
break;
}
}
return o && o.type ? (s.forEach((c) => c.classList.add("invalid")), o.errorElements = s) : s.forEach((c) => c.classList.add("valid")), o;
};
b(() => a.modelValue, () => {
y();
}), q(() => {
u != null && u.validationRules && Object.keys(n).forEach((d) => {
var s;
(s = u.validationRules[d]) != null && s.auto && b(() => n[d], () => {
y();
});
});
});
const v = () => {
i.value = "", a.target && document.querySelectorAll(a.target).forEach((s) => s.classList.remove("invalid", "valid"));
};
return F(() => {
v();
const d = f == null ? void 0 : f.findIndex((s) => s.id == r);
typeof d == "number" && d >= 0 && (f == null || f.splice(d, 1));
}), e({
errorMsg: i,
validate: y,
clear: v
}), (d, s) => i.value ? (A(), w("div", {
key: 0,
class: S(["_df_ErrMsg", d.$props.class])
}, D(i.value), 3)) : L("", !0);
}
}), T = {
install: (t, e) => {
t.component("DForm", j), t.component("DError", K);
let a = C;
e != null && e.customRules && (a = { ...a, ...e.customRules }), typeof (e == null ? void 0 : e.defaultMessages) == "object" && Object.keys(e == null ? void 0 : e.defaultMessages).forEach((l) => {
var i;
a[l] && ((i = e.defaultMessages) != null && i[l]) && (a[l].message = e.defaultMessages[l]);
});
const r = (l) => {
var i;
return ((i = l.value) != null && i.n ? a[l.type].message.replace(/{n}/g, l.value.n) : a[l.type].message) || l.type;
};
let f = "always";
typeof (e == null ? void 0 : e.activate) == "string" && ["always", "first_submit", "only_submit", "never"].indexOf(e.activate) > -1 && (f = e.activate);
let n = !1;
typeof (e == null ? void 0 : e.nativeValidate) == "boolean" && (n = e.nativeValidate);
const m = {
message: typeof (e == null ? void 0 : e.message) == "function" ? e.message : r,
validationRules: a,
activate: f,
nativeValidate: n
};
t.provide(V, m);
}
};
export {
K as DError,
j as DForm,
T as default
};