Last active
July 27, 2016 15:47
-
-
Save cjies/e65a62d859d32a3599960970c373e632 to your computer and use it in GitHub Desktop.
BEM.js helper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ------------------------------------- | |
// BEM Helper | |
// Inspired by 14islands/bem-helper-js | |
// @ref https://github.com/14islands/bem-helper-js | |
// | |
// Usage: | |
// const bem = BEM('header'); | |
// const bem2 = bem.element('title'); | |
// const bem3 = bem2.modifier('highlight'); | |
// | |
// bem.toString(); // => 'cj-header' | |
// bem2.toString(); // => 'cj-header__title' | |
// bem3.toString(); // => 'cj-header__title cj-header__title--highlight' | |
// | |
// or using in React: | |
// <header className={bem} /> | |
// ------------------------------------- | |
import classNamePrefix from './classname_prefix'; | |
const BEM_ELEMENT_SUFFIX = '__'; | |
const BEM_MODIFIER_SUFFIX = '--'; | |
function stringNotEmpty(string) { | |
return (typeof string === 'string' && string.length); | |
} | |
export class BEMFactory { | |
constructor({ block, element, modifiers = [], nonBemClasses = [] }) { | |
if (!block) { | |
throw new Error('block is required.'); | |
} | |
this._block = block; | |
this._element = element; | |
this._modifiers = modifiers; | |
this._nonBemClasses = nonBemClasses; | |
return this; | |
} | |
/** | |
* Set element scope | |
* @param {String} | |
* @return {BEMFactory} | |
*/ | |
element(elementIdentifier) { | |
if (stringNotEmpty(elementIdentifier)) { | |
return new BEMFactory({ | |
...this.toHash(), | |
element: elementIdentifier | |
}); | |
} | |
return this; | |
} | |
/** | |
* Add BEM modifier | |
* @param {String} | |
* @return {BEMFactory} | |
*/ | |
modifier(modifierIdentifier, isOn = true) { | |
if (isOn && stringNotEmpty(modifierIdentifier)) { | |
return new BEMFactory({ | |
...this.toHash(), | |
modifiers: [...this._modifiers, modifierIdentifier] | |
}); | |
} | |
return this; | |
} | |
/** | |
* Add other non-BEM classname to the mix | |
* @param {String} | |
* @return {BEMFactory} | |
*/ | |
add(className) { | |
if (stringNotEmpty(className)) { | |
return new BEMFactory({ | |
...this.toHash(), | |
nonBemClasses: [...this._nonBemClasses, className] | |
}); | |
} | |
return this; | |
} | |
/** | |
* Render BEM chain as full class name string | |
* | |
* @return {String} | |
*/ | |
toString() { | |
const prefix = typeof this._element !== 'undefined' ? | |
classNamePrefix(this._block) + BEM_ELEMENT_SUFFIX + this._element : | |
classNamePrefix(this._block); | |
const classes = [ | |
prefix, | |
...this._modifiers.map(modifier => prefix + BEM_MODIFIER_SUFFIX + modifier), | |
...this._nonBemClasses | |
]; | |
return classes.join(' '); | |
} | |
/** | |
* Export internal properties to a new Hash | |
* | |
* @return {Hash} | |
*/ | |
toHash() { | |
return { | |
block: this._block, | |
element: this._element, | |
modifiers: this._modifiers.slice(0), | |
nonBemClasses: this._nonBemClasses.slice(0) | |
}; | |
} | |
} | |
// Creates BEM chain based on context type | |
function BEM(blockName) { | |
if (typeof blockName === 'string') { | |
return new BEMFactory({ block: blockName }); | |
} | |
if (blockName instanceof BEMFactory) { | |
return blockName; | |
} | |
throw new Error('blockName should be a valid String or a BEMFactory instance.'); | |
} | |
export default BEM; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const CLASSNAME_PREFIX = 'cj'; | |
/** | |
* ClassName Prefix | |
* | |
* @param {String} className - Original ClassName | |
* @return {String} - ClassName within prefix | |
*/ | |
function classNamePrefix(className) { | |
if (!className) { | |
throw new Error('classNamePrefix: empty className'); | |
} | |
return `${CLASSNAME_PREFIX}-${className}`; | |
} | |
export default classNamePrefix; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment