vue-uform
Version:
Vue-uForm is an unstyled, flexible form validation library for Vue 3, focusing on component-driven design.
647 lines (646 loc) • 16.4 kB
JavaScript
import { defineComponent as g, provide as m, ref as d, nextTick as J, unref as O, h as v, inject as f, watch as $ } from "vue";
const N = Symbol("u-form-values"), k = Symbol("u-form-update-label"), U = Symbol("u-form-update-value"), L = Symbol("u-form-update-validator"), K = Symbol("u-form-submit"), _ = Symbol("u-form-submit-useid"), j = Symbol("form-scheme"), B = Symbol("form-reset-useid"), M = Symbol("form-reset-button"), D = Symbol("form-array-remove"), q = Symbol("form-array-push"), Q = g(
(e, t) => {
const r = Y(e.values);
m(N, r), m(k, (l, u) => {
Z(r, l, u);
}), m(U, (l, u) => {
x(r, l, u);
});
const n = d({});
m(L, (l, u) => {
n.value[l] = u;
}), m(D, (l, u) => {
ee(r.value, l, u);
}), m(q, (l, u) => {
te(r.value, l, u);
});
const a = d();
m(_, a), m(K, async () => {
a.value = Symbol("random"), await J();
let l = !1;
for (const u in n.value)
if (n.value[u] === !1) {
l = !0;
break;
}
l != !0 && t.emit("submit", X(O(r.value)));
}), e.scheme && m(j, e.scheme);
const i = d();
m(B, i), m(M, (l = {}) => {
s(l);
});
function s(l = {}) {
const u = w(r.value, l);
r.value = u, n.value = {}, i.value = Symbol("reset-useid");
}
return t.expose({ reset: s }), () => v("form", { class: "u-form" }, [
t.slots.default ? t.slots.default() : ""
]);
},
{
props: {
values: Object,
scheme: Function
},
emits: ["submit"]
}
);
function w(e, t) {
if (Array.isArray(e))
return e.map(
(r, n) => w(r, Array.isArray(t) ? t[n] : void 0)
);
if (e !== null && typeof e == "object" && !("value" in e && "label" in e && Object.keys(e).length <= 2)) {
const r = {};
for (const n in e)
r[n] = w(
e[n],
t && typeof t == "object" ? t[n] : void 0
);
return r;
} else {
let r = "";
return t !== void 0 && (r = t), {
label: e && typeof e == "object" && "label" in e ? e.label : "",
value: r
};
}
}
function C(e, t, r, n) {
if (!t) return;
const a = t.replace(/\[(\d+)\]/g, ".$1").split(".");
let i = e;
for (let s = 0; s < a.length; s++) {
const l = a[s];
if (s === a.length - 1) {
n !== void 0 ? (i[l] || (i[l] = { label: n, value: "" }), i[l].label = n) : (i[l] || (i[l] = { label: "", value: r }), i[l].value = r);
return;
}
if (!(l in i)) {
const u = a[s + 1];
/^\d+$/.test(u) ? i[l] = [] : i[l] = {};
}
i = i[l];
}
}
function X(e) {
function t(r) {
if (Array.isArray(r))
return r.map(t);
if (r && typeof r == "object") {
if ("value" in r && "label" in r && Object.keys(r).length <= 2)
return r.value;
const n = {};
for (const a in r)
n[a] = t(r[a]);
return n;
}
return r;
}
return t(e);
}
function Y(e) {
function t(n) {
if (Array.isArray(n))
return n.map((a) => t(a));
if (n !== null && typeof n == "object") {
const a = {};
for (const i in n)
a[i] = t(n[i]);
return a;
} else
return {
label: "",
value: n
};
}
const r = d({});
for (let n in e)
r.value[n] = t(e[n]);
return r;
}
function Z(e, t, r) {
C(e.value, t, void 0, r);
}
function x(e, t, r) {
C(e.value, t, r);
}
function ee(e, t, r) {
if (!t) return;
const n = t.replace(/\[(\d+)\]/g, ".$1").split(".");
let a = e;
for (let i = 0; i < n.length; i++) {
const s = n[i];
if (i === n.length - 1) {
if (a[s] == null && (a[s] = []), Array.isArray(a[s]))
a[s].splice(r, 1);
else
throw new Error("u-field-array must be bind an array value");
return;
}
if (!(s in a)) {
const l = n[i + 1];
/^\d+$/.test(l) ? a[s] = [] : a[s] = {};
}
a = a[s];
}
}
function te(e, t, r) {
if (!t) return;
const n = t.replace(/\[(\d+)\]/g, ".$1").split(".");
let a = e;
for (let i = 0; i < n.length; i++) {
const s = n[i];
if (i === n.length - 1) {
if (a[s] == null && (a[s] = []), Array.isArray(a[s]))
a[s].push(r);
else
throw new Error("u-field-array must be bind an array value");
return;
}
if (!(s in a)) {
const l = n[i + 1];
/^\d+$/.test(l) ? a[s] = [] : a[s] = {};
}
a = a[s];
}
}
const re = (e, t) => ({
node: e,
label: e.label,
args: t
}), I = {
required: ({ label: e }) => `${e} is required`,
number: ({ label: e }) => `${e} must be a number`,
confirm: ({ label: e }) => `${e} is not match`,
accept: ({ label: e }) => `Please accept the ${e}.`,
alpha: ({ label: e }) => `${e} can only contain alphabetical characters.`,
alphanumeric: ({ label: e }) => `${e} can only contain letters and numbers.`,
between: ({ label: e, args: t }) => `${e} must be between ${t[0]} and ${t[1]}.`,
email: ({ label: e }) => `${e} must be a email address`,
ends_with: ({ label: e, args: t }) => `${e} doesn’t end with ${t.join(",")}.`,
is: ({ label: e }) => `${e} is not an allowed value.`,
length: ({ label: e }) => `${e}'s length is not match.`,
lowercase: ({ label: e }) => `${e} can only contain lowercase letters.`,
max: ({ label: e, args: t }) => `${e} must be less than ${t[0]}`,
min: ({ label: e, args: t }) => `${e} must be greater than ${t[0]}`,
not: ({ label: e, node: t }) => `“${t.value}” is not an allowed ${e}.`,
starts_with: ({ label: e, args: t }) => `${e} doesn’t start with ${t.join(",")}.`,
uppercase: ({ label: e }) => `${e} can only contain uppercase letters.`,
url: () => "Please enter a valid URL."
};
function ne(e, t, ...r) {
if (!(e in I))
return "";
const n = I[e];
return n(re(t, r));
}
const ae = {
required: {
validator({ value: e }) {
return !!e;
}
},
number: {
validator({ value: e }) {
return !isNaN(e);
}
},
confirm: {
validator(e, t) {
const r = e.value, n = e.at(t).value;
return r === n;
}
},
accepted: {
validator({ value: e }) {
return ["yes", "on", "1", 1, !0, "true"].includes(e);
}
},
alpha: {
validator({ value: e }) {
return new RegExp("^\\p{L}+$", "u").test(String(e));
}
},
alphanumeric: {
validator({ value: e }) {
return /^[0-9\p{L}]+$/u.test(String(e));
}
},
between: {
validator({ value: e }, t, r) {
if (!isNaN(e) && !isNaN(t) && !isNaN(r)) {
const n = 1 * e;
t = Number(t), r = Number(r);
const [a, i] = t <= r ? [t, r] : [r, t];
return n >= 1 * a && n <= 1 * i;
}
return !1;
}
},
email: {
validator({ value: e }) {
return /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i.test(String(e));
}
},
ends_with: {
validator({ value: e }, ...t) {
return typeof e == "string" && t.length ? t.some((r) => e.endsWith(r)) : typeof e == "string" && t.length === 0;
}
},
is: {
validator({ value: e }, ...t) {
return t.some((r) => r == e);
}
},
length: {
validator({ value: e }, t = "0", r = "Infinity") {
const n = parseInt(t), a = r == "Infinity" ? 1 / 0 : parseInt(r), i = n <= a ? n : a, s = a >= n ? a : n;
if (typeof e == "string")
return e.length >= i && e.length <= s;
if (Array.isArray(e))
return e.length >= i && e.length <= s;
if (e && typeof e == "object") {
const l = Object.keys(e).length;
return l >= i && l <= s;
}
return !1;
}
},
lowercase: {
validator({ value: e }) {
return new RegExp("^\\p{Ll}+$", "u").test(String(e));
}
},
max: {
validator({ value: e }, t) {
return Array.isArray(e) ? e.length <= Number(t) : Number(e) <= Number(t);
}
},
min: {
validator({ value: e }, t) {
return Array.isArray(e) ? e.length >= Number(t) : Number(e) >= Number(t);
}
},
not: {
validator({ value: e }, ...t) {
return t.every((r) => r !== e);
}
},
starts_with: {
validator({ value: e }, ...t) {
return typeof e == "string" && t.length ? t.some((r) => e.startsWith(r)) : typeof e == "string" && t.length === 0;
}
},
uppercase: {
validator({ value: e }) {
return new RegExp("^\\p{Lu}+$", "u").test(String(e));
}
},
url: {
validator({ value: e }, ...t) {
try {
const r = t.length ? t : ["http:", "https:"], n = new URL(String(e));
return r.includes(n.protocol);
} catch {
return !1;
}
}
}
};
function ie(e) {
let t = ae;
for (const r in e)
t[r] = {
validator: e[r]
};
return t;
}
function se(e) {
let t = [];
return e === "" ? [] : (e.split("|").forEach((n) => {
const a = n.split(":");
let i = {
name: a[0],
params: []
};
a.length > 1 && (i.params = a[1].split(",")), t.push(i);
}), t);
}
function le(e, t, r, n) {
let a = [];
const i = ie(n);
return t.map((s) => {
if (!(s.name in i))
throw new Error(`invalid validation name "${s.name}"`);
let l = i[s.name].validator(e, ...s.params);
if (l !== !0) {
let u = ne(s.name, e);
typeof l == "string" && (u = l), r && s.name in r && (u = r[s.name]), a.push(u);
}
}), a.length === 0 ? !0 : a;
}
const T = Symbol("array-useid"), ue = g(
(e, t) => {
e.scheme && m(j, e.scheme);
const r = f(N, d({}));
f(
U,
void 0
);
let n = fe(r, e.name);
const a = d();
m(T, a);
const i = f(D, void 0), s = f(q, void 0);
return () => v("div", {}, [
t.slots.default ? t.slots.default({
fields: n,
insert: (l, u) => {
},
remove: (l) => {
i && i(e.name, l), a.value = Symbol();
},
push: (l) => {
const u = F(l);
s && s(e.name, u), a.value = Symbol();
}
}) : ""
]);
},
{
props: {
name: String,
scheme: Function
}
}
);
function oe(e) {
return e.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
}
function ce(e) {
return e && typeof e == "object" && "label" in e && "value" in e;
}
function F(e) {
if (ce(e))
return { label: e.label ?? "", value: e.value };
if (Array.isArray(e))
return e.map((t) => F(t));
if (e && typeof e == "object") {
const t = {};
for (const r in e)
t[r] = F(e[r]);
return t;
}
return { label: "", value: e };
}
function fe(e, t) {
const r = oe(t);
let n = e.value;
for (const a of r) {
if (n == null) return [];
if (Array.isArray(n)) {
const i = Number(a);
n = Number.isInteger(i) ? n[i] : void 0;
} else if (typeof n == "object" && a in n)
n = n[a];
else
return [];
}
return Array.isArray(n) ? n : [];
}
const me = g(
(e, t) => {
const r = f(N, d({}));
let n = de(r, e.name);
const a = f(
k,
void 0
), i = f(
U,
void 0
), s = f(
L,
void 0
);
a && a(e.name, e.label || "");
const l = f(_, d()), u = d([]), o = d(
n || e.modelValue || e.value || void 0
), h = d(!1), P = se(e.validation), A = () => {
const c = W(
{ name: e.name, label: e.label || "", value: o.value },
r
);
let y = le(
c,
P,
e.validationMessages,
e.rules
);
y !== !0 ? (h.value = !0, u.value = y, s && s(e.name, !1)) : (h.value = !1, u.value = [], s && s(e.name, !0));
};
$(l, () => {
A();
});
const z = f(B, d());
$(z, () => {
h.value = !1, u.value = [];
const c = V(r.value, e.name);
c.value ? o.value = c.value : o.value = "";
});
const G = f(T, d());
$(G, () => {
const c = V(r.value, e.name);
o.value = c.value;
});
const R = (c, y = "primitive") => {
if (y == "primitive")
o.value = c;
else if (y == "array")
if (Array.isArray(o.value)) {
const b = o.value.findIndex((p) => p == c);
b > -1 ? o.value.splice(b, 1) : o.value.push(c);
} else
throw new Error(
'update type is "array",the value except is an array type'
);
t.emit("update:modelValue", o.value), i && i(e.name, o.value), A();
};
if (e.custom)
return () => t.slots.default ? t.slots.default({
value: o.value,
update: R,
hasError: h.value,
messages: u.value
}) : "";
const S = f(j, void 0);
if (e.scheme || S) {
const c = P.map((b) => b.name);
let y = {
name: e.name,
label: e.label,
value: e.value || "",
valueRef: o,
help: e.help,
hasError: h,
messages: u,
validation_names: c,
slot: () => t.slots.default ? t.slots.default({
value: o.value,
update: (b, p = "primitive") => {
if (p == "primitive")
o.value = b;
else if (p == "array")
if (Array.isArray(o.value)) {
const E = o.value.findIndex(
(H) => H == b
);
E > -1 ? o.value.splice(E, 1) : o.value.push(b);
} else
throw new Error(
'update type is "array",the value except is an array type'
);
t.emit("update:modelValue", o.value), i && i(e.name, o.value), A();
}
}) : void 0
};
if (e.scheme)
return () => e.scheme(y);
if (S)
return () => S(y);
}
return () => v("div", { class: "u-field-wrap" }, [
v("div", { class: "u-field-input-wrap" }, [
v("label", { class: "u-label" }, e.label),
t.slots.default ? t.slots.default({
value: o.value,
update: R,
hasError: h.value,
messages: u.value
}) : ""
]),
v("div", { class: "u-field-help" }, e.help),
v(
"ul",
{ class: "u-validation-message" },
u.value.map((c) => v("li", c))
)
]);
},
{
props: {
name: String,
label: String,
help: String,
value: String,
modelValue: [String, Boolean, Array, Number],
scheme: Function,
custom: Boolean,
validation: {
type: String,
default: ""
},
validationMessages: Object,
rules: Object
},
emits: ["update:modelValue"]
}
);
function W(e, t) {
return {
...e,
at(r) {
const n = V(t.value, r);
return W(
{ name: r, label: n.label, value: n.value },
t
);
}
};
}
function de(e, t) {
if (!t)
return;
const r = t.replace(/\[(\w+)\]/g, ".$1").split(".");
let n = e.value;
for (let a = 0; a < r.length; a++) {
if (n == null) return;
const i = r[a];
if (typeof n == "object" && i in n)
n = n[i];
else if (Array.isArray(n) && !isNaN(Number(i)))
n = n[Number(i)];
else
return;
}
return n && typeof n == "object" && "value" in n ? n.value : n;
}
function V(e, t) {
if (!t) return e;
const r = t.replace(/\[(\d+)\]/g, ".$1").split(".");
let n = e;
for (let a of r) {
if (n == null) return;
n = n[a];
}
return n;
}
const ve = g(
(e, t) => {
const r = f(M);
return e.custom ? () => t.slots.default ? t.slots.default({
reset: r
}) : "" : () => v(
"button",
{
type: "button",
class: "u-reset",
onClick: () => {
r({});
}
},
t.slots.default ? t.slots.default() : "Reset"
);
},
{
props: {
custom: Boolean
},
emits: ["reset"]
}
), ye = g(
(e, t) => {
const r = f(K);
return e.custom ? () => t.slots.default ? t.slots.default({
submit: r
}) : "" : () => v(
"button",
{
type: "button",
class: "u-submit",
onClick: () => {
r();
}
},
t.slots.default ? t.slots.default() : "Submit"
);
},
{
props: {
custom: Boolean
},
emits: ["submit"]
}
), he = {
install(e, t = {}) {
e.component("u-form", Q), e.component("u-field", me), e.component("u-field-array", ue), e.component("u-submit", ye), e.component("u-reset", ve);
}
};
export {
me as Field,
ue as FieldArray,
Q as Form,
ve as Reset,
ye as Submit,
he as plugin
};