axentix
Version:
Axentix is a framework mixing fully customizable components & utility-first classes, leaving the design choice to the developer.
182 lines (181 loc) • 7.73 kB
JavaScript
const f = {
components: [],
plugins: [],
prefix: "ax",
mode: ""
}, p = (e) => `--${f.prefix}-${e}`, D = (e) => f.components.find((t) => t.name === e).class, k = () => {
const e = f.components.filter((s) => s.dataDetection), t = f.plugins.filter((s) => s.dataDetection);
return [...e, ...t].map((s) => s.name);
}, q = () => {
document.querySelectorAll("[data-ax]").forEach((t) => {
let s = t.dataset.ax;
if (s = s[0].toUpperCase() + s.slice(1).toLowerCase(), !k().includes(s)) {
console.error(
`[Axentix] Error: ${s} component doesn't exist.
Did you forget to register him ?`,
t
);
return;
}
try {
const o = D(s);
new o(`#${t.id}`);
} catch (o) {
console.error("[Axentix] Data: Unable to load " + s, o);
}
});
}, T = () => {
try {
new Axentix.Axentix("all");
} catch (e) {
console.error("[Axentix] Unable to auto init.", e);
}
};
document.addEventListener("DOMContentLoaded", () => {
document.documentElement.dataset.axentix && T(), q();
});
const $ = (e, t, s) => {
const o = new CustomEvent("ax." + t, {
detail: s || {},
bubbles: !0
});
e.dispatchEvent(o);
}, O = () => window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches, V = (e) => e.checkValidity() || e.validationMessage, P = (e, t) => {
const s = document.createElement("div");
s.axGenerated = !0, e.appendChild(s), s.classList.add("form-helper-invalid"), s.innerHTML = t;
}, B = (e) => {
const t = e.querySelector(".form-helper-invalid");
t && t.axGenerated && t.remove();
}, b = (e) => {
e.classList.remove("form-valid", "form-invalid", "form-no-helper"), B(e);
}, E = (e, t) => {
const s = e.getAttribute("data-form-validate");
let o = !1;
if (s) {
const a = s.toLowerCase().split(",");
if (o = a.includes("auto"), a.includes("lazy") && t === "input") return;
}
const r = V(e), n = e.closest(".form-field, .form-file");
return b(n), r !== !0 ? (o && typeof r == "string" ? P(n, r) : n.querySelector(".form-helper-invalid") || n.classList.add("form-no-helper"), n.classList.add("form-invalid"), !1) : (n.classList.add("form-valid"), n.querySelector(".form-helper-valid") || n.classList.add("form-no-helper"), !0);
}, H = (e) => {
e.querySelectorAll("[data-form-validate]").forEach((s) => b(s.closest(".form-field, .form-file")));
}, N = (e) => [...e.querySelectorAll("[data-form-validate]")].map((s) => E(s, "change")).every((s) => s);
let y = !0;
const m = (e) => {
e.forEach(A);
}, I = (e) => {
if (y) {
y = !1;
return;
}
setTimeout(() => {
m(e);
}, 10);
}, A = (e) => {
const t = e.closest(".form-field"), s = t.querySelector(".form-custom-select"), o = t.classList.contains("active"), r = ["date", "month", "week", "time"];
let n = s && e.tagName === "DIV" && e.innerText.length > 0;
s || (n = e.value.length > 0 || e.tagName !== "SELECT" && e.placeholder.length > 0 || e.tagName === "SELECT" || r.some((c) => e.matches(`[type="${c}"]`)));
const a = document.activeElement === e, l = e.hasAttribute("disabled") || e.hasAttribute("readonly");
e.firstInit ? (L(e, o, n, a, t, s), e.firstInit = !1, e.isInit = !0) : l || L(e, o, n, a, t, s);
}, L = (e, t, s, o, r, n) => {
const a = e.type === "textarea", l = r.querySelector("label:not(.form-check)");
!t && (s || o) ? r.classList.add("active") : t && !(s || o) && r.classList.remove("active"), a ? l && (l.style.backgroundColor = w(l)) : _(e, r, n, l), o && !a ? r.classList.add("is-focused") : n || r.classList.remove("is-focused"), o && a ? r.classList.add("is-textarea-focused") : r.classList.remove("is-textarea-focused");
}, _ = (e, t, s, o) => {
const r = e.clientWidth, n = e.offsetLeft, a = e.clientHeight + (s ? s.offsetTop : e.offsetTop) + "px", l = e.closest(".form-material").classList.contains("form-material-bordered");
t.style.setProperty(p("form-material-position"), a);
let c = n, v = "left", R = r + "px", g = 0;
t.classList.contains("form-rtl") && (v = "right", c = t.clientWidth - r - n), t.style.setProperty(p(`form-material-${v}-offset`), c + "px"), c != 0 && (g = n), t.style.setProperty(p("form-material-width"), R), o && (o.style.left = g + "px", l && (o.style.backgroundColor = w(o)));
}, x = (e) => {
const t = window.getComputedStyle(e).backgroundColor;
if (t && !["transparent", "rgba(0, 0, 0, 0)"].includes(t)) return t;
}, w = (e) => {
e.style.backgroundColor = "";
let t = e;
for (; t.parentElement; ) {
const o = x(t);
if (o) return o;
t = t.parentElement;
}
const s = x(document.documentElement);
return s || "white";
}, C = (e, t) => {
e.hasAttribute("data-form-validate") && E(e, t.type);
}, j = (e, t) => {
e.forEach((s) => {
s === t.target && A(s);
});
}, z = (e, t) => {
t.target.tagName === "FORM" && t.target.classList.contains("form-material") && I(e);
}, U = (e) => {
e.forEach((n) => {
n.firstInit = !0, n.validateRef = C.bind(null, n), n.addEventListener("input", n.validateRef), n.addEventListener("change", n.validateRef);
}), m(e);
const t = j.bind(null, e);
document.addEventListener("focus", t, !0), document.addEventListener("blur", t, !0);
const s = I.bind(null, e);
window.addEventListener("pageshow", s);
const o = z.bind(null, e);
document.addEventListener("reset", o);
const r = m.bind(null, e);
window.addEventListener("resize", r);
}, W = (e, t) => {
const s = e.files;
s.length > 1 ? t.innerHTML = Array.from(s).map((o) => o.name).join(", ") : s[0] && (t.innerHTML = s[0].name);
}, G = (e) => {
if (e.isInit) return;
e.isInit = !0;
const t = e.querySelector('input[type="file"]'), s = e.querySelector(".form-file-path");
t.handleRef = W.bind(null, t, s), t.validateRef = C.bind(null, t), t.addEventListener("change", t.handleRef), t.addEventListener("input", t.validateRef), t.addEventListener("change", t.validateRef);
}, J = () => {
const e = Array.from(document.querySelectorAll(".form-file"));
try {
e.forEach(G);
} catch (t) {
console.error("[Axentix] Form file error", t);
}
}, S = (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(
(o, r) => (r.isInit ? o.detectInputs.push(r) : o.setupInputs.push(r), o),
{ setupInputs: [], detectInputs: [] }
);
J();
try {
t.length > 0 && U(t), s.length > 0 && m(s);
} catch (o) {
console.error("[Axentix] Material forms error", o);
}
};
document.addEventListener("DOMContentLoaded", () => S());
const K = { updateInputs: S, validate: N, resetValidation: H };
let d = "system", i = "", h = !1;
const Q = () => {
h = !0, M();
}, X = () => h = !1, u = (e = "system") => {
h && (d = e, e === "system" && (e = O() ? "dark" : "light", localStorage.removeItem("ax-theme")), i && document.documentElement.classList.remove(i), i = `theme-${e}`, document.documentElement.classList.add(i), K.updateInputs(), $(document.documentElement, "theme.change", { theme: i }), d !== "system" && localStorage.setItem("ax-theme", i));
}, M = () => {
const e = localStorage.getItem("ax-theme");
u(e ? e.replace("theme-", "") : d);
}, Y = () => {
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => d === "system" && u("system")), M();
};
document.addEventListener("DOMContentLoaded", Y);
const Z = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
disable: X,
enable: Q,
get enabled() {
return h;
},
get theme() {
return i;
},
get themeMode() {
return d;
},
toggle: u
}, Symbol.toStringTag, { value: "Module" }));
export {
Z as Theme
};