@xobotyi/bem

The fastest BEM class name generator

Usage no npm install needed!

<script type="module">
  import xobotyiBem from 'https://cdn.skypack.dev/@xobotyi/bem';
</script>

README

@xobotyi/bem

The fastest BEM class name generator

NPM Version NPM Downloads NPM Dependents Build Coverage Types Tree Shaking


❤️Please consider starring this project to show your love and support.🙌

As handwriting BEM-compatible class names is quite painful and existing couple of packages are slow or lack of functionality needed for me (such as prefixing) — this package exists. Also as figures this package the fastest one I know about🚀

And turns this:

import * as react from "react";

export function component(){
  return (
    <div className="ns__blockName ns__blockName_size-l">
      <div className="ns__blockName__wrapperElement">
        <div className="ns__blockName__headerElement ns__blockName__headerElement_size-l">Block title</div>
        <button className="ns__blockName__buttonElement ns__blockName__buttonElement_left ns__blockName__buttonElement_size-l ns__blockName__buttonElement_disabled">Button left</button>
        <button className="ns__blockName__buttonElement ns__blockName__buttonElement_right ns__blockName__buttonElement_size-l">Button right</button>
      </div>
    </div>
  );
}

into this:

import * as react from "react";
import { BEM } from "@xobotyi/bem";

const bem = BEM.extend({prefix: "MY"}); // in real world this row will be a single per project
                                        // and initialized elsewhere
const b = bem.lock('blockName');

export function component(){
  return (
    <div className={ b({ size:'l' }) }>
      <div className={ b('wrapperElement') }>
        <div className={ b('headerElement', { size: 'l' }) }>Block title</div>
        <button className={ b('buttonElement', { 'left':true, size:'l', disabled:true }) }>Button left</button>
        <button className={ b('buttonElement', { 'right':true, size:'l' }) }>Button right</button>
      </div>
    </div>
  );
}

Installation note

This package written in TypeScript and delivered with 3 versions:

  • main field of package.json is pointing to transpiled ES5 version with CJS modules resolution;
  • module field is pointing to transpiled ES5 version with ES modules resolution;
  • esnext field is pointing to the ESNext version with ES modules resolution;

Depending on your targets you may have to use Webpack and/or Babel to pull untranspiled version of package. See some tips on wiring thing up: https://2ality.com/2017/06/pkg-esnext.html

Usage

Regular BEM

By default component provides default BEM syntax

import { BEM } from "@xobotyi/bem";

// blocks
BEM('block', ['large', 'disabled'], 'random_classname'); // block block_large block_disabled random_classname
// or
BEM('block', { size: 'large', disabled: true }); // block block_size_large block_disabled

// elements
BEM('block', 'element', { size: 'large' }); // block__element block__element_size_large
Syntax alternation

But you easily can alter any of separators as you wish, add prefix or make modifier-only generation as declared in BEViS syntax notation.

import { BEM } from "@xobotyi/bem";

const myBem = BEM.extend({
  prefix: 'PFX',
  prefixDelimiter: '__',
  elementDelimiter: '-',
  modifierDelimiter: '_',
  modifierValueDelimiter: '_',
  fullModifier: false,
});

// blocks
myBem('block', ['large', 'disabled']); // PFX__block _large _disabled
// or
myBem('block', { size: 'large', disabled: true }); // PFX__block _size_large _disabled

// elements
BEM('block', 'element', { size: 'large' }); // PFX__block-element _size_large
Block and Element baking

In order to improve performance it is possible to bake-in block and element name

import * as react from "react";
import { BEM } from "@xobotyi/bem";

const b = BEM.lock('block');

function render(){
  return (
    <div className={b()}>
      <span className={b('text', ['running'])}></span>
      <button className={b('button', { active: true })}></button>
    </div>
  );
}

Performance (recent benchmark results)

Benchmark results can be found in the benchmark directory.

To run benchmarks simply clone this repo and make yarn && yarn benchmark.

Related projects