UNPKG

axentix

Version:

Axentix is a framework mixing fully customizable components & utility-first classes, leaving the design choice to the developer.

118 lines (117 loc) 5.52 kB
const A = { components: [], plugins: [], prefix: "ax", mode: "" }, d = (e) => `--${A.prefix}-${e}`, R = (e) => e.checkValidity() || e.validationMessage, w = (e, t) => { const s = document.createElement("div"); s.axGenerated = !0, e.appendChild(s), s.classList.add("form-helper-invalid"), s.innerHTML = t; }, S = (e) => { const t = e.querySelector(".form-helper-invalid"); t && t.axGenerated && t.remove(); }, p = (e) => { e.classList.remove("form-valid", "form-invalid", "form-no-helper"), S(e); }, L = (e, t) => { const s = e.getAttribute("data-form-validate"); let r = !1; if (s) { const a = s.toLowerCase().split(","); if (r = a.includes("auto"), a.includes("lazy") && t === "input") return; } const n = R(e), o = e.closest(".form-field, .form-file"); return p(o), n !== !0 ? (r && typeof n == "string" ? w(o, n) : o.querySelector(".form-helper-invalid") || o.classList.add("form-no-helper"), o.classList.add("form-invalid"), !1) : (o.classList.add("form-valid"), o.querySelector(".form-helper-valid") || o.classList.add("form-no-helper"), !0); }, C = (e) => { e.querySelectorAll("[data-form-validate]").forEach((s) => p(s.closest(".form-field, .form-file"))); }, q = (e) => [...e.querySelectorAll("[data-form-validate]")].map((s) => L(s, "change")).every((s) => s); let m = !0; const c = (e) => { e.forEach(g); }, y = (e) => { if (m) { m = !1; return; } setTimeout(() => { c(e); }, 10); }, g = (e) => { const t = e.closest(".form-field"), s = t.querySelector(".form-custom-select"), r = t.classList.contains("active"), n = ["date", "month", "week", "time"]; let o = s && e.tagName === "DIV" && e.innerText.length > 0; s || (o = e.value.length > 0 || e.tagName !== "SELECT" && e.placeholder.length > 0 || e.tagName === "SELECT" || n.some((i) => e.matches(`[type="${i}"]`))); const a = document.activeElement === e, l = e.hasAttribute("disabled") || e.hasAttribute("readonly"); e.firstInit ? (h(e, r, o, a, t, s), e.firstInit = !1, e.isInit = !0) : l || h(e, r, o, a, t, s); }, h = (e, t, s, r, n, o) => { const a = e.type === "textarea", l = n.querySelector("label:not(.form-check)"); !t && (s || r) ? n.classList.add("active") : t && !(s || r) && n.classList.remove("active"), a ? l && (l.style.backgroundColor = I(l)) : M(e, n, o, l), r && !a ? n.classList.add("is-focused") : o || n.classList.remove("is-focused"), r && a ? n.classList.add("is-textarea-focused") : n.classList.remove("is-textarea-focused"); }, M = (e, t, s, r) => { const n = e.clientWidth, o = e.offsetLeft, a = e.clientHeight + (s ? s.offsetTop : e.offsetTop) + "px", l = e.closest(".form-material").classList.contains("form-material-bordered"); t.style.setProperty(d("form-material-position"), a); let i = o, f = "left", x = n + "px", u = 0; t.classList.contains("form-rtl") && (f = "right", i = t.clientWidth - n - o), t.style.setProperty(d(`form-material-${f}-offset`), i + "px"), i != 0 && (u = o), t.style.setProperty(d("form-material-width"), x), r && (r.style.left = u + "px", l && (r.style.backgroundColor = I(r))); }, v = (e) => { const t = window.getComputedStyle(e).backgroundColor; if (t && !["transparent", "rgba(0, 0, 0, 0)"].includes(t)) return t; }, I = (e) => { e.style.backgroundColor = ""; let t = e; for (; t.parentElement; ) { const r = v(t); if (r) return r; t = t.parentElement; } const s = v(document.documentElement); return s || "white"; }, b = (e, t) => { e.hasAttribute("data-form-validate") && L(e, t.type); }, T = (e, t) => { e.forEach((s) => { s === t.target && g(s); }); }, k = (e, t) => { t.target.tagName === "FORM" && t.target.classList.contains("form-material") && y(e); }, V = (e) => { e.forEach((o) => { o.firstInit = !0, o.validateRef = b.bind(null, o), o.addEventListener("input", o.validateRef), o.addEventListener("change", o.validateRef); }), c(e); const t = T.bind(null, e); document.addEventListener("focus", t, !0), document.addEventListener("blur", t, !0); const s = y.bind(null, e); window.addEventListener("pageshow", s); const r = k.bind(null, e); document.addEventListener("reset", r); const n = c.bind(null, e); window.addEventListener("resize", n); }, D = (e, t) => { const s = e.files; s.length > 1 ? t.innerHTML = Array.from(s).map((r) => r.name).join(", ") : s[0] && (t.innerHTML = s[0].name); }, $ = (e) => { if (e.isInit) return; e.isInit = !0; const t = e.querySelector('input[type="file"]'), s = e.querySelector(".form-file-path"); t.handleRef = D.bind(null, t, s), t.validateRef = b.bind(null, t), t.addEventListener("change", t.handleRef), t.addEventListener("input", t.validateRef), t.addEventListener("change", t.validateRef); }, B = () => { const e = Array.from(document.querySelectorAll(".form-file")); try { e.forEach($); } catch (t) { console.error("[Axentix] Form file error", t); } }, E = (e = document.querySelectorAll( ".form-material .form-field:not(.form-default) .form-control:not(.form-custom-select)" )) => { const { setupInputs: t, detectInputs: s } = Array.from(e).reduce( (r, n) => (n.isInit ? r.detectInputs.push(n) : r.setupInputs.push(n), r), { setupInputs: [], detectInputs: [] } ); B(); try { t.length > 0 && V(t), s.length > 0 && c(s); } catch (r) { console.error("[Axentix] Material forms error", r); } }; document.addEventListener("DOMContentLoaded", () => E()); const H = { updateInputs: E, validate: q, resetValidation: C }; export { H as Forms };