Skip to content

v2.0.1

Choose a tag to compare

@github-actions github-actions released this 21 May 12:23
· 19 commits to master since this release
cb2fcba

Migration guide: v1 -> v2

Version 2 simplifies the configuration API and makes the package ESM-only.

1. Package is ESM-only

CommonJS and UMD builds are no longer published.

Before:

const { bmc } = require('@rhapsodic/bem-classnames');

After:

import { bmc } from '@rhapsodic/bem-classnames';

If your project still uses CommonJS, migrate the consuming code to ESM or use
dynamic import:

const { bmc } = await import('@rhapsodic/bem-classnames');

2. booleanModifier was renamed to flag

The old helper was removed.

Before:

import { bmc, booleanModifier } from '@rhapsodic/bem-classnames';

const classNames = bmc('button', {
  modifiers: {
    isActive: booleanModifier('state', 'active'),
  },
});

After:

import { bmc, flag } from '@rhapsodic/bem-classnames';

const classNames = bmc('button', {
  modifiers: {
    isActive: flag('state', 'active'),
  },
});

3. stringModifier was renamed to variant

The old helper was removed.

Before:

import { bmc, stringModifier } from '@rhapsodic/bem-classnames';

const classNames = bmc('button', {
  modifiers: {
    variant: stringModifier('theme', {
      primary: 'brand',
      secondary: 'neutral',
    }),
  },
});

After:

import { bmc, variant } from '@rhapsodic/bem-classnames';

const classNames = bmc('button', {
  modifiers: {
    variant: variant('theme', {
      primary: 'brand',
      secondary: 'neutral',
    }),
  },
});

4. customModifiers was removed

Custom modifiers now live in the same modifiers object as regular prop
modifiers.

Before:

import { bmc, booleanModifier } from '@rhapsodic/bem-classnames';

interface ButtonProps {
  size: 'small' | 'large';
}

const classNames = bmc<ButtonProps>('button', {
  modifiers: {
    size: 'size',
  },
  customModifiers: {
    isLoading: booleanModifier('state', 'loading'),
  },
});

classNames({
  size: 'large',
  isLoading: true,
});

After:

import { bmc, flag } from '@rhapsodic/bem-classnames';

interface ButtonProps {
  size: 'small' | 'large';
}

const classNames = bmc<ButtonProps, { isLoading: boolean }>('button', {
  modifiers: {
    size: 'size',
    isLoading: flag('state', 'loading'),
  },
});

classNames({
  size: 'large',
  isLoading: true,
});

5. New direct shorthand syntax

You can now pass modifiers directly as the second bmc argument.

import { bmc, flag, variant } from '@rhapsodic/bem-classnames';

const classNames = bmc('button', {
  size: true,
  isActive: flag('state', 'active'),
  tone: variant('theme', {
    brand: 'primary',
  }),
});

classNames({
  size: 'large',
  isActive: true,
  tone: 'brand',
});
// ['button', 'button_size_large', 'button_state_active', 'button_theme_primary']

Direct shorthand automatically behaves like whitelist: true, so unrelated
props are not converted into classes.

6. whitelist: true

whitelist can now be true. In that mode, only keys configured in
modifiers are used.

const classNames = bmc('button', {
  modifiers: {
    size: true,
    isActive: flag('state', 'active'),
  },
  whitelist: true,
});

This is equivalent to the direct shorthand:

const classNames = bmc('button', {
  size: true,
  isActive: flag('state', 'active'),
});

7. Reserved keys in direct shorthand

In direct shorthand, modifiers and whitelist are treated as settings keys.
If your props are named modifiers or whitelist, use the explicit settings
syntax.

const classNames = bmc('button', {
  modifiers: {
    modifiers: true,
    whitelist: true,
  },
  whitelist: true,
});

8. Type changes

Some legacy exported types related to the old string/custom modifier API were
removed. Prefer the current public types:

import type {
  BooleanModifierSettings,
  StringModifierSettings,
  ModifiersSettings,
  BmcSettings,
  PropsWhitelist,
} from '@trenlok/bem-modifier-classes';

Quick checklist

  • Replace require(...) with ESM import.
  • Replace booleanModifier(...) with flag(...).
  • Replace stringModifier(...) with variant(...).
  • Move customModifiers entries into modifiers.
  • Add the second generic to bmc<TProps, TCustom>() when using custom
    modifiers.
  • Use direct shorthand for new code when possible.
    View changes on GitHub