@tenoxui/browser
Version:
A JavaScript library for creating highly customized, flexible, and extensible utility-first CSS framework
203 lines (202 loc) • 6.36 kB
JavaScript
import { TenoxUI as T } from "tenoxui";
import { TenoxUI as g } from "@tenoxui/moxie";
function x(l) {
return l.replace(/\\3(\d) /g, "$1").replace(/\\([#{}.:;?%&,@+*~'"!^$[\]()=>|/])/g, "$1");
}
class w extends T {
constructor({
// tenoxui configuration
moxie: s = g,
tabSize: e = 2,
values: t = {},
classes: i = {},
aliases: r = {},
property: n = {},
variants: a = {},
safelist: o = [],
typeOrder: h = [],
breakpoints: c = {},
moxieOptions: d = {},
selectorPrefix: u = "",
prefixLoaderOptions: p = {},
reservedVariantChars: f = [],
// dom options
apply: m = {},
watch: y = !0,
debounceDelay: E = 10,
processExisting: C = !0,
selector: b = "[class]",
styleId: v = "tenoxui-browser-id"
} = {}) {
super({
moxie: s,
values: t,
aliases: r,
classes: i,
tabSize: e,
property: n,
variants: a,
safelist: o,
typeOrder: h,
breakpoints: c,
moxieOptions: d,
selectorPrefix: u,
prefixLoaderOptions: p,
reservedVariantChars: f
}), this.apply = m, this.watch = y, this.styleId = v, this.selector = b, this.updateTimeout = null, this.debounceDelay = E, this.processExisting = C, this.observer = null, this.styleElement = null, this.isInitialized = !1, this.processedClasses = /* @__PURE__ */ new Set();
}
/**
* Initialize the TenoxUI instance
*/
init() {
return this.isInitialized ? (console.warn("TenoxUI is already initialized"), this) : (this.createStyleElement(), this.processExisting && this.scanAndProcessClasses(), this.watch && this.startObserving(), this.isInitialized = !0, this);
}
/**
* Create or get the style element for injecting CSS
*/
createStyleElement() {
return this.styleElement = document.getElementById(this.styleId), this.styleElement || (this.styleElement = document.createElement("style"), this.styleElement.id = this.styleId, this.styleElement.setAttribute("data-tenoxui", "true"), document.head.appendChild(this.styleElement)), this.styleElement;
}
/**
* Scan existing elements and process their classes
*/
scanAndProcessClasses() {
const s = document.querySelectorAll(this.selector), e = /* @__PURE__ */ new Set();
s.forEach((t) => {
const i = t.classList;
i.length > 0 && i.forEach((r) => {
r.trim() && e.add(r);
});
}), e.size > 0 && this.processClasses(Array.from(e));
}
/**
* Create styles from CSS and apply configuration
*/
createStyles(s) {
const e = this.render(this.apply);
return this.injectCSS(e + `
` + s);
}
/**
* Process an array of class names and generate CSS
*/
processClasses(s) {
const e = s.filter((t) => !this.processedClasses.has(t));
e.length !== 0 && (e.forEach((t) => this.processedClasses.add(t)), this.createStyles(this.render(e)));
}
/**
* Inject CSS into the style element
*/
injectCSS(s) {
return this.styleElement && s.trim() && (this.styleElement.textContent += `
` + s), this;
}
/**
* Start observing DOM changes for new classes
*/
startObserving() {
if (!window.MutationObserver) {
console.warn("MutationObserver not supported, dynamic class detection disabled");
return;
}
this.observer = new MutationObserver((s) => {
this.debouncedUpdate(() => {
this.handleMutations(s);
});
}), this.observer.observe(document.body, {
childList: !0,
subtree: !0,
attributes: !0,
attributeFilter: ["class"]
});
}
/**
* Handle DOM mutations and extract new classes
*/
handleMutations(s) {
const e = /* @__PURE__ */ new Set();
s.forEach((t) => {
if (t.type === "attributes" && t.attributeName === "class") {
const i = t.target;
i.classList && i.classList.forEach((r) => {
r.trim() && !this.processedClasses.has(r) && e.add(r);
});
}
t.type === "childList" && t.addedNodes.length > 0 && t.addedNodes.forEach((i) => {
i.nodeType === Node.ELEMENT_NODE && this.extractClassesFromElement(i, e);
});
}), e.size > 0 && this.processClasses(Array.from(e));
}
/**
* Extract classes from an element and its descendants
*/
extractClassesFromElement(s, e) {
s.classList && s.classList.forEach((i) => {
i.trim() && !this.processedClasses.has(i) && e.add(i);
}), s.querySelectorAll("[class]").forEach((i) => {
i.classList.forEach((r) => {
r.trim() && !this.processedClasses.has(r) && e.add(r);
});
});
}
/**
* Debounce updates to avoid excessive processing
*/
debouncedUpdate(s) {
this.updateTimeout && clearTimeout(this.updateTimeout), this.updateTimeout = setTimeout(s, this.debounceDelay);
}
/**
* Manually add classes for processing
*/
addClass(...s) {
const e = [];
for (const t of s)
Array.isArray(t) ? e.push(...t) : t && e.push(t);
return this.processClasses(e), this;
}
/**
* Rescan existing elements for classes
*/
rescan() {
return this.scanAndProcessClasses(), this;
}
/**
* Clear all processed classes and rescan
*/
refresh() {
return this.processedClasses.clear(), this.styleElement && (this.styleElement.textContent = ""), this.scanAndProcessClasses(), this;
}
/**
* Stop observing DOM changes
*/
stopObserving() {
return this.observer && (this.observer.disconnect(), this.observer = null), this;
}
/**
* Destroy the TenoxUI instance and clean up resources
*/
destroy() {
return this.stopObserving(), this.styleElement && (this.styleElement.remove(), this.styleElement = null), this.updateTimeout && (clearTimeout(this.updateTimeout), this.updateTimeout = null), this.processedClasses.clear(), this.isInitialized = !1, this;
}
/**
* Get status information about the current instance
*/
status() {
const s = Array.from(this.processedClasses), e = this.getRulesData(s), t = this.process(s);
return {
processedClasses: [s.length, s],
validClasses: [
e.length,
t ? t.map((i) => x(i.className)) : []
],
isObserving: !!this.observer,
isInitialized: this.isInitialized,
styleElementExists: !!this.styleElement
};
}
}
export {
w as TenoxUI,
w as default
};
//# sourceMappingURL=index.es.js.map