Created
July 7, 2020 11:30
-
-
Save brookjordan/7db9bdbf20c7c9756e9262659c7da86f to your computer and use it in GitHub Desktop.
BEM-style class name builder
This file contains 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
/** | |
* Used like: | |
* const cls = buildBEMBuilder("block-name"); | |
* | |
* let blockClass = cls(); | |
* // => "block-name" | |
* | |
* let modifiedBlockClass = cls({ | |
* goodModifier: true, | |
* badModifier: false, | |
* }); | |
* // => "block-name block-name--good-modifier" | |
* | |
* let elementClass = cls('an-element'); | |
* // => "block-name__an-element" | |
* | |
* let modifiedElementClass = cls('an-element', { | |
* aModifier: true, | |
* anotherModifier: true, | |
* }); | |
* // => "block-name__an-element block-name__an-element--a-modifier block-name__an-element--another-modifier" | |
**/ | |
type Modifier = { [key: string]: boolean }; | |
const FALSY_CHECKS = { | |
true<T>(condition: T) { return typeof condition !== 'boolean' || condition === false }, | |
truthy<T>(condition: T) { return !condition }, | |
nullish<T>(condition: T) { return (typeof condition === 'boolean' && condition === false) || condition == null }, | |
}; | |
type FalsyCheckName = keyof typeof FALSY_CHECKS; | |
let [ modifierCheckStyle ]: FalsyCheckName[] = (Object.keys(FALSY_CHECKS) as FalsyCheckName[]); | |
function dasherize(str: string) { | |
return str | |
.replace(/_/g, "-") | |
.replace(/[A-Z]/g, char => `-${char.toLowerCase()}`) | |
.replace(/^-+/g, ""); | |
} | |
function buildBEMBuilder(_blockName: string) { | |
const blockName = dasherize(_blockName); | |
return function combineWithElementAndModifiers(element: (string | Modifier), modifiers: Modifier = {}) { | |
const falseCheck = FALSY_CHECKS[modifierCheckStyle]; | |
if (!element) { return blockName; } | |
let elementClass = blockName; | |
if (typeof element === "string") { | |
elementClass += `__${dasherize(element)}`; | |
} | |
if (typeof element === "object") { | |
modifiers = element; | |
} | |
if (!modifiers) { return elementClass; } | |
return [ | |
elementClass, | |
...Object.keys(modifiers) | |
.filter((modifier) => !falseCheck(modifiers[modifier])) | |
.map((modifier) => { | |
return `${elementClass}--${dasherize(modifier)}`; | |
}), | |
].join(' '); | |
} | |
} | |
Object.defineProperty(buildBEMBuilder, "modifierCheckStyle", { | |
get() { | |
return modifierCheckStyle; | |
}, | |
set(requestedCheckStyle: FalsyCheckName) { | |
modifierCheckStyle = requestedCheckStyle; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment