arto
Version:
Arto is a flexible and type-safe class name management library for building scalable UIs with variants, states, and conditional styling.
827 lines (826 loc) • 27.7 kB
JavaScript
var b = Object.defineProperty;
var V = (a, s, t) => s in a ? b(a, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[s] = t;
var o = (a, s, t) => V(a, typeof s != "symbol" ? s + "" : s, t);
class A extends Error {
/**
* Constructs a new ArtoError instance with a prefixed message.
* @param message - The original error message (automatically prefixed).
*/
constructor(s) {
super(`[Arto Error]: ${s}`), this.name = "ArtoError";
}
}
const g = (a) => {
throw new A(a);
}, h = (a, s) => {
const t = /* @__PURE__ */ new Set(), e = [a], i = /* @__PURE__ */ new Set();
for (; e.length > 0; ) {
const n = e.pop();
if (n != null)
if (typeof n == "string")
n.split(/\s+/).filter(Boolean).forEach((r) => t.add(r));
else if (Array.isArray(n))
for (let r = n.length - 1; r >= 0; r--)
e.push(n[r]);
else if (typeof n == "function") {
if (i.has(n)) {
console.warn("Cyclic class function detected:", n);
continue;
}
i.add(n);
try {
const r = n(s);
r && e.push(r);
} catch (r) {
r instanceof Error ? g(`Error resolving class function: ${r.message}`) : g(`Error resolving class function: ${String(r)}`);
}
} else
process.env.NODE_ENV !== "production" && console.warn("Unsupported class input type:", typeof n, "Value:", n);
}
return Array.from(t);
};
function P(a) {
return a ? new Set(
Object.entries(a).filter(([, s]) => s === !0).map(([s]) => s)
) : /* @__PURE__ */ new Set();
}
const v = (a) => typeof a == "string" || Array.isArray(a) || typeof a == "function", B = (a, s = {}) => {
const t = { ...a };
for (const e in s)
s[e] != null && (t[e] = s[e]);
return t;
};
class x {
constructor() {
/**
* Internal list of registered plugins. This array is not sorted by default.
* Sorting occurs later in the build process.
*/
o(this, "plugins", []);
}
/**
* Registers a single plugin in the registry, replacing any existing plugin with the same ID.
* @param plugin - The plugin to register.
* @example
* ```ts
* globalPlugins.register({
* id: 'my-plugin',
* stage: 'before',
* order: 10,
* apply(builder) {
* builder.addBaseClasses(['my-base-class'])
* }
* })
* ```
*/
register(s) {
!s.id && process.env.NODE_ENV !== "production" && g("Plugin must have a non-empty id."), this.plugins.findIndex((e) => e.id === s.id) !== -1 && (console.debug(`Plugin with id '${s.id}' is being replaced.`), this.unregister(s.id)), this.plugins.push(s);
}
/**
* Unregisters a plugin by its unique ID.
* @param id - The plugin ID to remove.
*/
unregister(s) {
const t = this.plugins.findIndex((e) => e.id === s);
t !== -1 && this.plugins.splice(t, 1);
}
/**
* Registers multiple plugins at once, applying the same logic as `register` for each.
* @param plugins - Array of plugin objects to register.
* @example
* ```ts
* globalPlugins.registerBatch([
* {
* id: 'plugin-a',
* stage: 'before',
* apply(builder) {
* builder.addBaseClasses(['plugin-a-class'])
* }
* },
* {
* id: 'plugin-b',
* stage: 'after',
* order: -1,
* apply(builder) {
* builder.addBaseClasses(['plugin-b-class'])
* }
* }
* ])
* ```
*/
registerBatch(s) {
for (const t of s)
this.register(t);
}
/**
* Retrieves all registered plugins, in the order they were inserted.
* Final sorting is handled at build time by `ClassNameBuilder`.
* @returns An array of plugins.
*/
getPlugins() {
return [...this.plugins];
}
/**
* Returns all plugins that match a specific stage ('before', 'core', or 'after'),
* without sorting by `order`.
* @param stage - The stage to filter plugins by.
* @returns A filtered list of plugins for the given stage.
*/
getByStage(s) {
return this.plugins.filter((t) => t.stage === s);
}
/**
* Removes all plugins from the registry.
* @example
* ```ts
* globalPlugins.clear()
* // now the registry is empty
* ```
*/
clear() {
this.plugins = [];
}
}
const j = new x();
class k {
/**
* Constructs a new `BaseClassNamePlugin`.
* @param order - Numeric order within the 'core' stage (default = 0).
*/
constructor(s = 0) {
/**
* A unique identifier for this plugin to help with debugging or HMR consistency.
*/
o(this, "id", "arto/Internal/AddBaseClassesPlugin");
/**
* The plugin stage; defaults to `'core'`, meaning it runs alongside Arto's internal logic.
*/
o(this, "stage", "core");
/**
* The priority order within the `'core'` stage; lower values run first.
* @default 0
*/
o(this, "order");
this.order = s;
}
/**
* Applies the top-level `className` from the Arto configuration to the builder's base classes,
* after normalizing it with `normalizeClassName`.
*
* @param builder - The `ClassNameBuilder` that accumulates class names from all plugins.
*/
apply(s) {
const t = s.getArtoConfig(), e = s.getContext();
if (t.className) {
const i = h(t.className, e);
s.addBaseClasses(i);
}
}
}
const m = (a) => typeof a == "object" && a !== null && "className" in a, I = (a) => m(a) ? a.className : v(a) ? a : g("Invalid configuration for className. Expected ClassName or StateConfig."), y = (a, s, t) => a ? typeof a == "function" ? a(s, t) : a.every((e) => {
var i;
return typeof e == "string" ? s.has(e) : !((i = e.not) != null && i.some((n) => s.has(n)));
}) : !0;
class O {
/**
* Constructs a new `StatesPlugin` that applies classes for top-level (global) states.
*
* @param stateConfigs - A mapping of state names to either class names or `StateConfig`.
* @param order - Plugin execution priority within the 'core' stage (default = 0).
*/
constructor(s, t = 0) {
o(this, "id", "arto/Internal/ApplyStateClassesPlugin");
o(this, "stage", "core");
o(this, "order");
/**
* A map of state keys to either simple class names or detailed `StateConfig`.
* For each active state, this plugin checks the config, verifies dependencies,
* and merges the resulting class names into the builder.
*/
o(this, "stateConfigs");
this.stateConfigs = s, this.order = t;
}
/**
* Called automatically by Arto during the plugin lifecycle. Checks each active state:
* 1. If a `StateConfig` is found, verify `dependsOn`.
* 2. Normalize the class names via `normalizeClassName`.
* 3. Add those class names to the builder's global state classes.
*
* @param builder - The `ClassNameBuilder` handling class name aggregation.
*/
apply(s) {
const t = s.getActiveStates(), e = s.getContext();
for (const i of t) {
const n = this.stateConfigs[i];
if (!n || m(n) && !y(n.dependsOn, t, e))
continue;
const r = h(I(n), e);
s.addGlobalStateClasses(i, r);
}
}
}
function E(a) {
if (typeof a != "object" || a === null)
return !1;
const s = a;
return "className" in s || "states" in s;
}
class D {
/**
* Constructs a `VariantsPlugin` with an optional `order`.
* @param order - Plugin priority in the 'core' stage (default = 0).
*/
constructor(s = 0) {
/**
* Unique ID for the plugin to help with debugging or HMR consistency.
*/
o(this, "id", "arto/Internal/ApplyVariantClassesPlugin");
/**
* Runs at the 'core' stage by default.
*/
o(this, "stage", "core");
/**
* The order (priority) among 'core' plugins. Lower means earlier execution.
* @default 0
*/
o(this, "order");
this.order = s;
}
/**
* Called automatically by the builder. Iterates through each variant key in the Arto config,
* checks the user's chosen value for that variant, and applies the appropriate class names.
*
* @param builder - The `ClassNameBuilder` to which classes are added.
*/
apply(s) {
const t = s.getArtoConfig(), e = s.getSelectedVariants(), i = s.getContext();
if (!t.variants) return;
const n = Object.keys(t.variants);
for (const r of n) {
const l = e[r];
if (l == null) continue;
const f = t.variants[r];
if (!f) continue;
const c = f[l];
c || g(
`Invalid value '${String(l)}' for variant '${String(r)}'.`
);
const u = this.processVariantConfig(
r,
c,
s,
i
);
s.addVariantClasses(r, u);
}
}
/**
* Determines how to handle a specific variant config:
* 1) If it's a direct `ClassName` (string, array, or function), normalize and return it.
* 2) If it's a `VariantConfig`, process the base `className` and then any nested states.
* 3) Otherwise, throw an error.
*
* @param variantKey - The variant key (e.g., 'size', 'color').
* @param variantConfig - The config for the chosen variant value.
* @param builder - The `ClassNameBuilder` instance.
* @param context - Optional context object.
* @returns A string array of normalized classes for this variant.
*/
processVariantConfig(s, t, e, i) {
if (v(t))
return h(t, i);
if (E(t)) {
const n = t.className ? h(t.className, i) : [];
return t.states && this.mergeVariantStates(s, t.states, e, i), n;
}
return g("Invalid variant configuration item encountered."), [];
}
/**
* Merges any variant-level states by iterating through each state definition.
* If a state is valid (either a direct class name or a `StateConfig`), the resulting
* classes are stored in the builder's `variantStateClasses`.
*
* @param variantKey - The key of the variant whose states we're processing.
* @param statesObj - The object containing state definitions for this variant.
* @param builder - The `ClassNameBuilder` instance to store classes.
* @param context - Optional context object for callbacks or state checks.
*/
mergeVariantStates(s, t, e, i) {
const n = e.getActiveStates();
for (const [r, l] of Object.entries(t)) {
if (!l) continue;
const f = r;
if (v(l)) {
const c = h(l, i);
e.addVariantStateClasses(s, f, c);
} else if (m(l)) {
if (!y(l.dependsOn, n, i)) continue;
const c = h(l.className, i);
e.replaceVariantStateClasses(s, f, c);
} else
g(`Invalid state config for state '${r}' ...`);
}
}
}
function N(a, s) {
switch (s ?? "AND") {
case "AND":
return a.every(Boolean);
case "OR":
return a.some(Boolean);
case "NOT":
return a.every((e) => !e);
case "XOR":
return a.filter(Boolean).length === 1;
case "IMPLIES":
return a.length < 2 ? !0 : !a[0] || a[1];
default:
return a.every(Boolean);
}
}
function w(a, s, t) {
const { variants: e = "AND", states: i = "AND", combine: n = "AND" } = t, r = e === "AND" ? a.every(Boolean) : a.some(Boolean), l = i === "AND" ? s.every(Boolean) : s.some(Boolean);
return n === "AND" ? r && l : r || l;
}
class L {
/**
* @param order - Numeric priority in the 'core' stage.
*/
constructor(s = 0) {
/**
* A unique ID for this plugin. Used for debugging or HMR consistency.
*/
o(this, "id", "arto/Internal/RulesPlugin");
/**
* Runs at the 'core' stage by default. Typically assigned a higher `order`
* so that state and variant classes are already applied before rules run.
*/
o(this, "stage", "core");
/**
* Plugin priority within the 'core' stage (default = 0).
* Often set to a higher value (e.g., 3) in `arto.ts`.
*/
o(this, "order");
this.order = s;
}
/**
* Main entry point called by the builder. Iterates over each rule in `artoConfig.rules`,
* checks whether the rule conditions pass, and if so:
* 1) Removes classes (per `rule.remove`).
* 2) Adds classes (per `rule.add`).
*
* @param builder - The builder that manages class buckets for variants, states, etc.
*/
apply(s) {
const t = s.getArtoConfig();
if (!t.rules) return;
const e = s.getActiveStates(), i = s.getSelectedVariants(), n = s.getContext();
for (const r of t.rules) {
const { when: l, remove: f, add: c } = r;
if (this.doesRuleApply(l, i, e, n) && (f && this.removeStuff(s, f), c)) {
const u = h(c, n);
s.addBaseClasses(u);
}
}
}
/**
* Evaluates whether a rule's `when` conditions are met using variants, states,
* and optional logic operations.
*
* @param when - Specifies which variants and states must match, plus an optional logic definition.
* @param selectedVariants - The user's chosen variant values.
* @param activeStates - The set of active states.
* @param context - Optional context for custom logic callbacks.
* @returns `true` if the rule should apply, otherwise `false`.
*/
doesRuleApply(s, t, e, i) {
const n = {};
if (s.variants) {
const c = Object.keys(s.variants);
for (const u of c) {
const p = s.variants[u];
if (!p) continue;
const d = t[u];
n[u] = d != null && p.includes(d);
}
}
const r = {};
if (s.states)
for (const c of s.states)
r[c] = e.has(c);
const l = [...Object.values(n), ...Object.values(r)];
if (!s.logic)
return N(l, "AND");
if (typeof s.logic == "string")
return N(l, s.logic);
if (typeof s.logic == "object") {
const c = Object.values(n), u = Object.values(r);
return w(c, u, s.logic);
}
const f = {
variantMatches: n,
stateMatches: r,
selectedVariants: t,
activeStates: e
};
return s.logic(f, i);
}
/**
* Removes classes from the builder according to the `ArtoRuleRemove` settings:
* - Clears variant classes for specified variant keys.
* - Clears state classes for specified states, possibly with a `statesScope`.
* - Clears all base classes if `remove.base` is true.
*
* @param builder - The ClassNameBuilder managing class buckets.
* @param remove - The removal instructions (variant keys, states, base).
*/
removeStuff(s, t) {
if (t.variants)
for (const e of t.variants)
s.clearVariantClasses(e);
if (t.states) {
const e = t.statesScope ?? "all";
for (const i of t.states)
if ((e === "all" || e === "global") && s.clearGlobalStateClasses(i), e === "all" || e === "variant")
for (const [n] of Object.entries(s.getSelectedVariants()))
s.clearVariantStateClasses(n, i);
}
t.base && s.clearBaseClasses();
}
}
const C = class C {
/**
* @param artoConfig - The main Arto configuration object describing base classes, variants, states, and rules.
* @param selectedVariants - The user-selected variants. Keys match `TVariants`, values are chosen at runtime.
* @param activeStates - A set of currently active states (e.g., 'disabled').
* @param context - An optional context object (e.g., user data, environment).
* @param plugins - A list of plugins that modify or extend class building logic.
*/
constructor(s, t, e, i, n) {
/**
* Base class names, applied before any variant or state classes.
*/
o(this, "baseClassNames", []);
/**
* A mapping of each variant key to an array of classes. These classes are applied
* after `baseClassNames` and can be overridden by state-level classes or subsequent rules.
*/
o(this, "variantClassNames", {});
/**
* A nested mapping of `[variantKey][stateName] => string[]` for variant-level states.
* Classes here are applied after standard variant classes if the corresponding state is active.
*/
o(this, "variantStateClassNames", {});
/**
* A mapping of global state names to an array of classes. Applied if the state is active.
* These classes override or supplement existing classes from base or variants.
*/
o(this, "globalStateClassNames", {});
/**
* A set of callbacks to run **after** 'core' plugins but **before** 'after' plugins.
*/
o(this, "postCoreCallbacks", []);
/**
* A new set of callbacks that run truly "post-build," i.e. after the 'after' stage.
*/
o(this, "finalBuildCallbacks", []);
/**
* An array of all plugins (local + global + internal), unsorted by default. Sorting
* occurs by stage -> order when applying them sequentially in `build()`.
*/
o(this, "allPlugins");
this.artoConfig = s, this.selectedVariants = t, this.activeStates = e, this.context = i;
const r = n ?? [];
for (const l of r)
l.stage || (l.stage = "core"), typeof l.order != "number" && (l.order = 0);
r.sort((l, f) => {
const c = C.stagePriority[l.stage] - C.stagePriority[f.stage];
return c !== 0 ? c : (l.order ?? 0) - (f.order ?? 0);
}), this.allPlugins = r;
}
/**
* Builds and returns the final array of class names by:
* 1) Running 'before' plugins.
* 2) Running 'core' plugins.
* 3) Executing any `postCoreCallbacks`.
* 4) Running 'after' plugins.
* 5) Executing any `finalBuildCallbacks`
* 6) Combining and returning all class buckets.
*
* @returns The combined list of classes (no deduplication), typically joined by spaces.
*
* @example
* ```ts
* const builder = new ClassNameBuilder(config, { size: 'small' }, new Set(['disabled']), ...)
* const classArray = builder.build()
* // => ['base-class', 'small-class', 'disabled-class']
* ```
*/
build() {
for (const t of this.allPlugins)
t.stage === "before" && t.apply(this);
for (const t of this.allPlugins)
t.stage === "core" && t.apply(this);
for (const t of this.postCoreCallbacks)
t();
for (const t of this.allPlugins)
t.stage === "after" && t.apply(this);
for (const t of this.finalBuildCallbacks)
t();
const s = [];
s.push(...this.baseClassNames);
for (const t in this.variantClassNames)
s.push(...this.variantClassNames[t]);
for (const t in this.variantStateClassNames) {
const e = this.variantStateClassNames[t];
if (e)
for (const i of this.activeStates) {
const n = e[i];
n && s.push(...n);
}
}
for (const t in this.globalStateClassNames)
s.push(...this.globalStateClassNames[t]);
return s;
}
// -------------------------------------------------------------------------
// Callbacks
// -------------------------------------------------------------------------
/**
* Adds a callback to run immediately after 'core' plugins but before 'after' plugins.
*
* @param callback - A function to run after the core logic has completed.
*
* @example
* ```ts
* builder.addPostCoreCallback(() => {
* console.log('Classes have been generated!')
* })
* ```
*/
addPostCoreCallback(s) {
this.postCoreCallbacks.push(s);
}
/**
* Adds a callback to run after all plugins have completed, including 'after' stage.
*
* @param callback - A function to run after all plugins have completed.
*
* @example
* ```ts
* builder.addFinalBuildCallback(() => {
* console.log('All classes have been generated!')
* })
* ```
*/
addFinalBuildCallback(s) {
this.finalBuildCallbacks.push(s);
}
// -------------------------------------------------------------------------
// Base Classes
// -------------------------------------------------------------------------
/**
* Appends an array of classes to the base bucket.
*
* @param classNames - An array of class names (e.g. `['btn', 'btn-primary']`).
*/
addBaseClasses(s) {
this.baseClassNames.push(...s);
}
/**
* Clears all previously added base classes.
*/
clearBaseClasses() {
this.baseClassNames = [];
}
/**
* Retrieves a copy of the current base classes for inspection or debugging.
*
* @returns A new array containing all base class names.
*/
getBaseClasses() {
return [...this.baseClassNames];
}
// -------------------------------------------------------------------------
// Variant Classes
// -------------------------------------------------------------------------
/**
* Appends classes for a specific variant key.
*
* @param variantKey - The name of the variant (e.g. `'size'`).
* @param classNames - The classes to add (e.g. `['text-sm', 'py-1']`).
*/
addVariantClasses(s, t) {
this.variantClassNames[s] || (this.variantClassNames[s] = []), this.variantClassNames[s].push(...t);
}
/**
* Replaces all classes for the given variant with a new array of classes.
*
* @param variantKey - The variant name to replace.
* @param classNames - The new classes.
*/
replaceVariantClasses(s, t) {
this.variantClassNames[s] = [...t];
}
/**
* Clears any existing classes assigned to a given variant.
*
* @param variantKey - The variant name.
*/
clearVariantClasses(s) {
this.variantClassNames[s] = [];
}
/**
* Retrieves a read-only copy of the full map of variant classes.
*
* @returns An object with each variant key mapped to an array of class names.
*/
getVariantClassMap() {
const s = {};
for (const t in this.variantClassNames)
s[t] = [...this.variantClassNames[t] ?? []];
return s;
}
// -------------------------------------------------------------------------
// Global State Classes
// -------------------------------------------------------------------------
/**
* Adds classes to the global state bucket. If `state` is active, these classes
* will be appended to the final output (after variant classes).
*
* @param state - The state name (e.g. `'disabled'`).
* @param classNames - The classes to add (e.g. `['opacity-50', 'pointer-events-none']`).
*/
addGlobalStateClasses(s, t) {
this.globalStateClassNames[s] || (this.globalStateClassNames[s] = []), this.globalStateClassNames[s].push(...t);
}
/**
* Replaces existing global state classes for the given `state` with a new array.
*
* @param state - The state name.
* @param classNames - The new array of classes.
*/
replaceGlobalStateClasses(s, t) {
this.globalStateClassNames[s] = [...t];
}
/**
* Clears any global state classes registered under the specified `state`.
*
* @param state - The state name to clear (e.g., 'hover').
*/
clearGlobalStateClasses(s) {
this.globalStateClassNames[s] = [];
}
/**
* Returns a copy of the classes for a specific global state, for inspection or debugging.
*
* @param state - The state name.
* @returns An array of class names, which may be empty if none are set.
*/
getGlobalStateClassesFor(s) {
return [...this.globalStateClassNames[s] ?? []];
}
// -------------------------------------------------------------------------
// Variant-Level State Classes
// -------------------------------------------------------------------------
/**
* Appends classes for a combination of variant key + state name.
* These will only be applied if the corresponding variant value is selected and the state is active.
*
* @param variantKey - The variant key (e.g. 'size').
* @param state - The state name (e.g. 'disabled').
* @param classNames - An array of classes to add.
*/
addVariantStateClasses(s, t, e) {
this.variantStateClassNames[s] || (this.variantStateClassNames[s] = {}), this.variantStateClassNames[s][t] || (this.variantStateClassNames[s][t] = []), this.variantStateClassNames[s][t].push(...e);
}
/**
* Replaces all classes for a specific `(variantKey, state)` pair.
*
* @param variantKey - The variant key.
* @param state - The state name.
* @param classNames - The new array of classes.
*/
replaceVariantStateClasses(s, t, e) {
this.variantStateClassNames[s] || (this.variantStateClassNames[s] = {}), this.variantStateClassNames[s][t] = [...e];
}
/**
* Clears all classes for a specific `(variantKey, state)` pair.
*
* @param variantKey - The variant key to clear.
* @param state - The state name to clear.
*/
clearVariantStateClasses(s, t) {
this.variantStateClassNames[s] && (this.variantStateClassNames[s][t] = []);
}
/**
* Retrieves classes for a given `(variantKey, state)` combination.
*
* @param variantKey - The variant key (e.g. 'color').
* @param state - The state name (e.g. 'hover').
* @returns An array of classes if they exist; otherwise an empty array.
*/
getVariantStateClasses(s, t) {
var e;
return (e = this.variantStateClassNames[s]) != null && e[t] ? [...this.variantStateClassNames[s][t]] : [];
}
// -------------------------------------------------------------------------
// Additional Getters & Setters
// -------------------------------------------------------------------------
/**
* Returns the original Arto configuration provided to this builder.
*
* @returns A readonly version of `ArtoConfig`.
*/
getArtoConfig() {
return this.artoConfig;
}
/**
* Retrieves the user-selected variants (merged with any default variants).
*
* @returns An object mapping each variant key to the selected value.
*/
getSelectedVariants() {
return this.selectedVariants;
}
/**
* Replaces the current selection of variants with a new mapping.
*
* @param variants - The new variant key/value mapping.
*/
setSelectedVariants(s) {
this.selectedVariants = s;
}
/**
* Retrieves the set of currently active states.
*
* @returns A `Set` of active state names.
*/
getActiveStates() {
return this.activeStates;
}
/**
* Replaces the set of active states.
*
* @param states - The new set of states (e.g. `new Set(['disabled', 'hover'])`).
*/
setActiveStates(s) {
this.activeStates = s;
}
/**
* Returns the optional context object, if any, used by plugins or class generation callbacks.
*/
getContext() {
return this.context;
}
/**
* Retrieves all classes from base, variants, global states, and variant-level states.
*
* @returns An array containing all classes.
*/
getAllClasses() {
const s = [];
s.push(...this.baseClassNames);
for (const t in this.variantClassNames)
s.push(...this.variantClassNames[t]);
for (const t of this.activeStates)
s.push(...this.getGlobalStateClassesFor(t));
for (const t of Object.keys(this.selectedVariants))
for (const e of this.activeStates) {
const i = this.getVariantStateClasses(t, e);
s.push(...i);
}
return s;
}
};
/**
* Maps each plugin stage to a numeric value used for sorting:
* - 'before' -> 0
* - 'core' -> 1
* - 'after' -> 2
*/
o(C, "stagePriority", {
before: 0,
core: 1,
after: 2
});
let S = C;
const $ = (a, s) => ((!a || typeof a != "object") && g("Invalid config provided to arto."), (t) => {
const e = (t == null ? void 0 : t.variants) ?? {}, i = a.defaultVariants ?? {}, n = (t == null ? void 0 : t.states) ?? {}, r = t == null ? void 0 : t.context, l = B(i, e), f = P(n), c = [...s || [], ...j.getPlugins()], u = [];
a.className && u.push(new k()), a.variants && u.push(new D()), a.states && u.push(new O(a.states)), a.rules && a.rules.length > 0 && u.push(new L(3));
const p = [...c, ...u];
return new S(
a,
l,
f,
r,
p
).build().join(" ");
});
export {
S as ClassNameBuilder,
x as PluginRegistry,
$ as arto,
h as normalizeClassName,
j as pluginHub
};