const typeface = { sans: "sans serif", serif: "Times New Roman" }; const sizes = { small: "1rem", large: "3rem" }; const colors = { red: "#ff2200", blue: "#0022ff" }; const styles = new Map(); function Mapper>(className:string, propertyName:string, lut:T) { const build =(_:T, propertyValue:string, customPropertyName?:string)=> { const selector = `${className}-${(customPropertyName||propertyValue as string).replace(/[^a-zA-Z0-9]/g, "")}${activeQuery?"_"+activeQuery:""}`; const check = styles.get(selector); if(!check) { const body = `{ ${propertyName}:${propertyValue}; }`; styles.set(selector, activeQuery ? `{ @media(${activeQuery})${body}}` : body); } return selector; } type UseCustom = (custom:string)=>string; return new Proxy(function(override:string) { return build(lut, override); } as UseCustom, { get(target, prop){ return build(lut, lut[prop as string], prop as string); } } ) as T & UseCustom; } export function Complex, F extends CallableFunction>(obj:Obj, func:F) { return new Proxy(func, {get(target, prop){ return obj[prop as string] }}) as Obj & F } let activeQuery:false|string = false function Query(amount:string) { activeQuery = amount; return (...args:string[])=> { activeQuery = false; return args.join(" "); } } export function config(obj:T) { const CSS = { Sheet() { const rules = []; for(const [key, value] of styles.entries()) { rules.push(key+value); } return rules.join("\n"); }, get MD() { return Query("768px"); }, Face: Mapper("Face", "font-family", {...typeface, ...obj}), Pad: Mapper("P", "padding", sizes) }; return CSS; } export default config({});