BEM class names generator for TypeScript
npm install bem-ts

BEM (_Block Element Modifier_) class names generator for TypeScript.
Inspired by bem-cn.
- No extra features.
- No dependencies.
- TypeScript support.
``shell`
npm install bem-ts
A basic usage:
`typescript
import bem from "bem-ts";
const b = bem("block");
b();
//=> "block"
b({ mod1: true, mod2: false });
//=> "block block--mod1"
b({ mod1: true, mod2: false, mod3: true });
//=> "block block--mod1 block--mod3"
b(["mod1", null, "mod3"]);
//=> "block block--mod1 block--mod3"
b("element");
//=> "block__element"
b("element", { mod1: true, mod2: false });
//=> "block__element block__element--mod1"
b("element", { mod1: true, mod2: false, mod3: true });
//=> "block__element block__element--mod1 block__element--mod3"
b("element", ["mod1", null, "mod3"]);
//=> "block__element block__element--mod1 block__element--mod3"
`
A more complex example using React and CSS (closer to the real world):
`tsx
// Button.tsx
import React from "react";
import bem from "bem-ts";
import "./Button.css";
const b = bem("Button");
type Props = {
state: "success" | "danger";
icon: React.ReactNode;
children: React.ReactNode;
};
export function Button({ state, icon, children }: Props) {
return (
);
}
`
`css`
/ Button.css /
.Button {
/ Block /
}
.Button--success {
/ Modifier /
}
.Button--danger {
/ Modifier /
}
.Button__icon {
/ Element /
}
.Button__icon--success {
/ Element's modifier /
}
.Button__icon--danger {
/ Element's modifier /
}

The bem() function receives a block name and creates a new function that generates class names. The created function can receive elements or modifiers.
The function can receive the following options:
| Name | Type | Default |
| ------------------------------------------- | -------------------- | ------- |
| elementDelimiter | string | "__" |modifierDelimiter
| | string | "--" |namespace
| | string, string[] | "" |namespaceDelimiter
| | string | "-" |strict
| | boolean | true |
#### elementDelimiter
`typescript
const b = bem("block", { elementDelimiter: "_" });
b("element");
//=> "block_element"
`
#### modifierDelimiter
`typescript
const b = bem("block", { modifierDelimiter: "-" });
b({ mod: true });
//=> block "block-mod"
b("element", { mod: true });
//=> "block__element block__element-mod"
`
#### namespace
`typescript
const b = bem("block", { namespace: "ns" });
b();
//=> "ns-block"
b("element", { mod1: true, mod2: true });
//=> "ns-block__element ns-block__element--mod1 ns-block__element--mod2"
`
`typescript
const b = bem("block", { namespace: ["ns1", "ns2"] });
b();
//=> "ns1-ns2-block"
b("element", { mod1: true, mod2: true });
//=> "ns1-ns2-block__element ns1-ns2-block__element--mod1 ns1-ns2-block__element--mod2"
`
#### namespaceDelimiter
`typescript
const b = bem("block", { namespace: "ns", namespaceDelimiter: "---" });
b();
//=> "ns---block"
b("element", { mod1: true, mod2: true });
//=> "ns---block__element ns---block__element--mod1 ns---block__element--mod2"
`
When namespace is not given, namespaceDelimiter will be ignored.
`typescript
const b = bem("block", { namespaceDelimiter: "---" });
b();
//=> "block"
b("element", { mod1: true, mod2: true });
//=> "block__element block__element--mod1 block__element--mod2"
`
#### strict
When you set true to this option, given elements or modifiers are checked. And if the check fails, then a runtime error is thrown.
For example, when setting true, the following code throws an error.
`typescript`
const b = bem("foo", { strict: true });
b("element__");
b({ modifier--: true });
When setting false, the following code throws no errors.
`typescript`
const b = bem("foo", { strict: false });
b("element__");
//=> foo__element__
b({ modifier_: true });
//=> foo__modifier_
The setup() function can change the default options.
`typescript
import bem, { setup } from "bem-ts";
setup({
elementDelimiter: "_",
modifierDelimiter: "-",
namespace: "ns",
namespaceDelimiter: "---",
strict: false,
});
const b = bem("block");
b("element", { mod: true });
//=> "ns---block_element ns---block_element-mod"
``
MIT © Masafumi Koba