UNPKG

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
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 };