arto
Version:
Arto is a flexible and type-safe class name management library for building scalable UIs with variants, states, and conditional styling.
2 lines (1 loc) • 9.59 kB
JavaScript
"use strict";var A=Object.defineProperty;var P=(a,s,t)=>s in a?A(a,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[s]=t;var o=(a,s,t)=>P(a,typeof s!="symbol"?s+"":s,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class B extends Error{constructor(s){super(`[Arto Error]: ${s}`),this.name="ArtoError"}}const h=a=>{throw new B(a)},g=(a,s)=>{const t=new Set,e=[a],i=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?h(`Error resolving class function: ${r.message}`):h(`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 x(a){return a?new Set(Object.entries(a).filter(([,s])=>s===!0).map(([s])=>s)):new Set}const S=a=>typeof a=="string"||Array.isArray(a)||typeof a=="function",j=(a,s={})=>{const t={...a};for(const e in s)s[e]!=null&&(t[e]=s[e]);return t};class y{constructor(){o(this,"plugins",[])}register(s){!s.id&&process.env.NODE_ENV!=="production"&&h("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)}unregister(s){const t=this.plugins.findIndex(e=>e.id===s);t!==-1&&this.plugins.splice(t,1)}registerBatch(s){for(const t of s)this.register(t)}getPlugins(){return[...this.plugins]}getByStage(s){return this.plugins.filter(t=>t.stage===s)}clear(){this.plugins=[]}}const b=new y;class O{constructor(s=0){o(this,"id","arto/Internal/AddBaseClassesPlugin");o(this,"stage","core");o(this,"order");this.order=s}apply(s){const t=s.getArtoConfig(),e=s.getContext();if(t.className){const i=g(t.className,e);s.addBaseClasses(i)}}}const v=a=>typeof a=="object"&&a!==null&&"className"in a,k=a=>v(a)?a.className:S(a)?a:h("Invalid configuration for className. Expected ClassName or StateConfig."),V=(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 I{constructor(s,t=0){o(this,"id","arto/Internal/ApplyStateClassesPlugin");o(this,"stage","core");o(this,"order");o(this,"stateConfigs");this.stateConfigs=s,this.order=t}apply(s){const t=s.getActiveStates(),e=s.getContext();for(const i of t){const n=this.stateConfigs[i];if(!n||v(n)&&!V(n.dependsOn,t,e))continue;const r=g(k(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{constructor(s=0){o(this,"id","arto/Internal/ApplyVariantClassesPlugin");o(this,"stage","core");o(this,"order");this.order=s}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 u=t.variants[r];if(!u)continue;const c=u[l];c||h(`Invalid value '${String(l)}' for variant '${String(r)}'.`);const f=this.processVariantConfig(r,c,s,i);s.addVariantClasses(r,f)}}processVariantConfig(s,t,e,i){if(S(t))return g(t,i);if(E(t)){const n=t.className?g(t.className,i):[];return t.states&&this.mergeVariantStates(s,t.states,e,i),n}return h("Invalid variant configuration item encountered."),[]}mergeVariantStates(s,t,e,i){const n=e.getActiveStates();for(const[r,l]of Object.entries(t)){if(!l)continue;const u=r;if(S(l)){const c=g(l,i);e.addVariantStateClasses(s,u,c)}else if(v(l)){if(!V(l.dependsOn,n,i))continue;const c=g(l.className,i);e.replaceVariantStateClasses(s,u,c)}else h(`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{constructor(s=0){o(this,"id","arto/Internal/RulesPlugin");o(this,"stage","core");o(this,"order");this.order=s}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:u,add:c}=r;if(this.doesRuleApply(l,i,e,n)&&(u&&this.removeStuff(s,u),c)){const f=g(c,n);s.addBaseClasses(f)}}}doesRuleApply(s,t,e,i){const n={};if(s.variants){const c=Object.keys(s.variants);for(const f of c){const p=s.variants[f];if(!p)continue;const m=t[f];n[f]=m!=null&&p.includes(m)}}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),f=Object.values(r);return w(c,f,s.logic)}const u={variantMatches:n,stateMatches:r,selectedVariants:t,activeStates:e};return s.logic(u,i)}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{constructor(s,t,e,i,n){o(this,"baseClassNames",[]);o(this,"variantClassNames",{});o(this,"variantStateClassNames",{});o(this,"globalStateClassNames",{});o(this,"postCoreCallbacks",[]);o(this,"finalBuildCallbacks",[]);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,u)=>{const c=C.stagePriority[l.stage]-C.stagePriority[u.stage];return c!==0?c:(l.order??0)-(u.order??0)}),this.allPlugins=r}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}addPostCoreCallback(s){this.postCoreCallbacks.push(s)}addFinalBuildCallback(s){this.finalBuildCallbacks.push(s)}addBaseClasses(s){this.baseClassNames.push(...s)}clearBaseClasses(){this.baseClassNames=[]}getBaseClasses(){return[...this.baseClassNames]}addVariantClasses(s,t){this.variantClassNames[s]||(this.variantClassNames[s]=[]),this.variantClassNames[s].push(...t)}replaceVariantClasses(s,t){this.variantClassNames[s]=[...t]}clearVariantClasses(s){this.variantClassNames[s]=[]}getVariantClassMap(){const s={};for(const t in this.variantClassNames)s[t]=[...this.variantClassNames[t]??[]];return s}addGlobalStateClasses(s,t){this.globalStateClassNames[s]||(this.globalStateClassNames[s]=[]),this.globalStateClassNames[s].push(...t)}replaceGlobalStateClasses(s,t){this.globalStateClassNames[s]=[...t]}clearGlobalStateClasses(s){this.globalStateClassNames[s]=[]}getGlobalStateClassesFor(s){return[...this.globalStateClassNames[s]??[]]}addVariantStateClasses(s,t,e){this.variantStateClassNames[s]||(this.variantStateClassNames[s]={}),this.variantStateClassNames[s][t]||(this.variantStateClassNames[s][t]=[]),this.variantStateClassNames[s][t].push(...e)}replaceVariantStateClasses(s,t,e){this.variantStateClassNames[s]||(this.variantStateClassNames[s]={}),this.variantStateClassNames[s][t]=[...e]}clearVariantStateClasses(s,t){this.variantStateClassNames[s]&&(this.variantStateClassNames[s][t]=[])}getVariantStateClasses(s,t){var e;return(e=this.variantStateClassNames[s])!=null&&e[t]?[...this.variantStateClassNames[s][t]]:[]}getArtoConfig(){return this.artoConfig}getSelectedVariants(){return this.selectedVariants}setSelectedVariants(s){this.selectedVariants=s}getActiveStates(){return this.activeStates}setActiveStates(s){this.activeStates=s}getContext(){return this.context}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}};o(C,"stagePriority",{before:0,core:1,after:2});let d=C;const R=(a,s)=>((!a||typeof a!="object")&&h("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=j(i,e),u=x(n),c=[...s||[],...b.getPlugins()],f=[];a.className&&f.push(new O),a.variants&&f.push(new D),a.states&&f.push(new I(a.states)),a.rules&&a.rules.length>0&&f.push(new L(3));const p=[...c,...f];return new d(a,l,u,r,p).build().join(" ")});exports.ClassNameBuilder=d;exports.PluginRegistry=y;exports.arto=R;exports.normalizeClassName=g;exports.pluginHub=b;