Skip to content

Instantly share code, notes, and snippets.

@sachin-hg
Last active January 20, 2023 12:14
Show Gist options
  • Save sachin-hg/4e0f773adc304163625d5042d6a71727 to your computer and use it in GitHub Desktop.
Save sachin-hg/4e0f773adc304163625d5042d6a71727 to your computer and use it in GitHub Desktop.
const cache = {}
const Obj = function (js, css, nonAtomic) {
this.__isAtomic = true
this.js = js
this.css = css
this.nonAtomic = nonAtomic
}
Obj.prototype.toString = function () {
return this.css + (this.nonAtomic.length ? ' ' + this.nonAtomic : '')
}
const getClassName = (js, css, nonAtomic = '') => {
const key = js + css + nonAtomic
// maintaining a cache because returning new references everytime might lead to useless react rerenders
let obj = cache[key]
if (!obj) {
obj = new Obj(js, css, nonAtomic)
cache[key] = obj
}
return obj
}
const cx = function () {
const presentClassNames = arguments
const length = presentClassNames.length
const atomicClasses = {}
let nonAtomic = ''
let atomicKey = ''
let atomicValue = ''
for (let i = length - 1; i >= 0; i--) {
let cls = presentClassNames[i]
if (cls) {
if (cls.__isAtomic) {
const keys = cls.js.split(' ')
const values = cls.css.split(' ')
if (cls.nonAtomic) {
nonAtomic += (nonAtomic.length ? ' ' : '') + cls.nonAtomic
}
const length = keys.length
for (let i = length - 1; i >= 0; i--) {
const keyHash = keys[i]
const value = values[i]
if (!atomicClasses[keyHash]) {
atomicClasses[keyHash] = value
atomicKey += (atomicKey.length ? ' ' : '') + keyHash
atomicValue += (atomicValue.length ? ' ' : '') + value
}
}
} else {
nonAtomic += (nonAtomic.length ? ' ' : '') + cls
}
}
}
return atomicValue.length ? getClassName(atomicKey, atomicValue, nonAtomic) : nonAtomic
}
// example usage
const style1 = getClassName('fs wt bg', 'a b c') // getClassName function call will be created by a babel-plugin or linaria
const style2 = getClassName('fs cl', 'd e')
const style3 = getClassName('fs bg', 'f g')
const style4 = getClassName('fs wt', 'h j')
cx(cx(style1, false && style2, style3, 'non-atomic', false && 'cta'), style4).toString() // in real world usage there wont be a need to manually call toString
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment