Options
All
  • Public
  • Public/Protected
  • All
Menu

Bem React

Набор утилит для разработки пользовательских интерфейсов по БЭМ-методологии на React. Bem React поддерживает аннотации типов TypeScript и Flow.

Описание концепции

Основая мысль — работаем через полную композицию. Работу с CSS-классами и модификаторы выражаем через HOCи, а переопределение кода по платформам и экспериментам через DI.

Необходимое от БЭМ в React

Состав пакетов

Модификатор (withBemMod) более не сможет влиять на внутреннее устройство компонента. Дополнительная функциональность должна быть выражена через управляющие компоненты сверху. А сами компоненты могут быть выражены как React.ComponentType по необходимости без каких-либо базовых БЭМ-компонентов. Подключение модификаторов не отличается от подключения любых других HOC и работает через любой compose.

Работа с CSS-классами состоит из трех этапов:

  • статическое создание базового CSS-класса сущности;
  • динамическое добавление CSS-классов модификаторов;
  • динамическое добавление CSS-классов миксов.

Статическое создание CSS-классов выражается через функцию-хелпер (@bem-react/classname).

Динамическое добавление CSS-классов выражается через HOC (withBemMod) модификатора с единственным требованием к внешнему интерфейсу компонента в виде опционального пропса className. Модификатор определит истинность предиката и добавит дополнительный класс через пропсы к базовому классу через ту же функцию-хелпер, что используется и для статических CSS-классов.

Переопределение компонентов и их составляющих выражается через dependency injection (DI) (@bem-react/di), который реализуется на базе React.ContextAPI и множественных реестров (Registry) компонентов. Каждый компонент волен регистрировать свои зависимости в реестре и позволять переопределять их сверху, что напрямую не заложено в работу контекста, но реализуется способом резолвинга во время провайдинга нового значения контекста. По умолчанию зависимости возможно переопределять и по контексту вниз, что есть стандартный механизм работы контекста. В итоге, DI — это HOC, который провайдит реестры в контекст. Реестры могут работать в режимах проваливания и всплытия зависимостей. Это позволяет переопределять что угодно, где угодно, на любом уровне вложенности, простым дописыванием в нужный реестр.

Внести вклад

Bem React является библиотекой с открытым исходным кодом, которая находится в стадии активной разработки, а также используется внутри компании Яндекс.

Если у вас есть предложения по улучшению API, вы можете прислать Pull Request.

Если вы нашли ошибку, вы можете создать issue с описанием проблемы.

Подробное руководство по внесению изменений см. в CONTRIBUTING.md.

Лицензия

© 2018 Яндекс. Код выпущен под Mozilla Public License 2.0.

Index

Type aliases

ClassNameFormatter

ClassNameFormatter: function

BEM Entity className formatter.

@bem-react/classname

Type declaration

ClassNameInitilizer

ClassNameInitilizer: function

BEM Entity className initializer.

@bem-react/classname

Type declaration

ClassNameList

ClassNameList: Array<string | undefined>

List of classname.

@bem-react/classname

Composition

Composition: function

Type declaration

    • <U>(fn: U): StatelessComponent<JSX.LibraryManagedAttributes<U, ExtractProps<U>> & T>
    • Type parameters

      • U: ComponentType<any>

      Parameters

      • fn: U

      Returns StatelessComponent<JSX.LibraryManagedAttributes<U, ExtractProps<U>> & T>

Enhance

Enhance: function

Type declaration

    • (WrappedComponent: ComponentType<T>): ComponentType<T>
    • Parameters

      • WrappedComponent: ComponentType<T>

      Returns ComponentType<T>

ExtractProps

ExtractProps: ExtractProps<T>

GetNonDefaultProps

GetNonDefaultProps: GetNonDefaultProps<T>

NoStrictEntityMods

NoStrictEntityMods: Record<string, string | boolean | number | undefined>

Allowed modifiers format.

see

https://en.bem.info/methodology/key-concepts/#modifier

@bem-react/classname

RegistryContext

RegistryContext: Record<string, Registry>

Wrapper

Wrapper: function

Type declaration

    • (WrappedComponent: ComponentType): ComponentType<T>
    • Parameters

      • WrappedComponent: ComponentType

      Returns ComponentType<T>

Variables

Const RegistryConsumer

RegistryConsumer: ExoticComponent<ConsumerProps<object>> = registryContext.Consumer

Const cn

cn: function = withNaming({e: '-',m: '_',})

BEM Entity className initializer with React naming preset.

example

import { cn } from '@bem-react/classname';

const cat = cn('Cat');

cat(); // Cat
cat({ size: 'm' }); // Cat_size_m
cat('Tail'); // Cat-Tail
cat('Tail', { length: 'small' }); // Cat-Tail_length_small

const dogPaw = cn('Dog', 'Paw');

dogPaw(); // Dog-Paw
dogPaw({ color: 'black', exists: true }); // Dog-Paw_color_black Dog-Paw_exists
see

https://en.bem.info/methodology/naming-convention/#react-style

@bem-react/classname

Type declaration

Functions

Const ComponentRegistryConsumer

classnames

  • classnames(...strings: Array<string | undefined>): string
  • classNames merge function.

    example
    
    import { classnames } from '@bem-react/classname';
    
    classnames('Block', 'Mix', undefined, 'Block'); // 'Block Mix'

    Parameters

    • Rest ...strings: Array<string | undefined>

      classNames strings

    Returns string

compose

  • compose<T1>(fn1: Wrapper<T1>): Composition<T1>
  • compose<T1, T2>(fn1: Wrapper<T1>, fn2: Wrapper<T2>): keyof T1 extends keyof T2 ? Composition<T1 | T2> : Composition<T1 & T2>
  • compose<T1, T2, T3>(fn1: Wrapper<T1>, fn2: Wrapper<T2>, fn3: Wrapper<T3>): keyof T1 extends keyof T2 ? Composition<T1 | T2 | T3> : Composition<T1 & T2 & T3>
  • compose<T1, T2, T3, T4>(fn1: Wrapper<T1>, fn2: Wrapper<T2>, fn3: Wrapper<T3>, fn4: Wrapper<T4>): keyof T1 extends keyof T2 ? Composition<T1 | T2 | T3 | T4> : Composition<T1 & T2 & T3 & T4>
  • compose<T1, T2, T3, T4, T5>(fn1: Wrapper<T1>, fn2: Wrapper<T2>, fn3: Wrapper<T3>, fn4: Wrapper<T4>, fn5: Wrapper<T5>): keyof T1 extends keyof T2 ? Composition<T1 | T2 | T3 | T4 | T5> : Composition<T1 & T2 & T3 & T4 & T5>
  • compose<T1, T2, T3, T4, T5, T6>(fn1: Wrapper<T1>, fn2: Wrapper<T2>, fn3: Wrapper<T3>, fn4: Wrapper<T4>, fn5: Wrapper<T5>, fn6: Wrapper<T6>): keyof T1 extends keyof T2 ? Composition<T1 | T2 | T3 | T4 | T5 | T6> : Composition<T1 & T2 & T3 & T4 & T5 & T6>
  • compose<T1, T2, T3, T4, T5, T6, T7>(fn1: Wrapper<T1>, fn2: Wrapper<T2>, fn3: Wrapper<T3>, fn4: Wrapper<T4>, fn5: Wrapper<T5>, fn6: Wrapper<T6>, fn7: Wrapper<T7>): keyof T1 extends keyof T2 ? Composition<T1 | T2 | T3 | T4 | T5 | T6 | T7> : Composition<T1 & T2 & T3 & T4 & T5 & T6 & T7>
  • compose<T1, T2, T3, T4, T5, T6, T7, T8>(fn1: Wrapper<T1>, fn2: Wrapper<T2>, fn3: Wrapper<T3>, fn4: Wrapper<T4>, fn5: Wrapper<T5>, fn6: Wrapper<T6>, fn7: Wrapper<T7>, fn8: Wrapper<T8>): keyof T1 extends keyof T2 ? Composition<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8> : Composition<T1 & T2 & T3 & T4 & T5 & T6 & T7 & T8>
  • compose(...fns: Array<Wrapper<any>>): Composition<any>

withBemMod

withNaming

withRegistry

  • withRegistry(...registries: Registry[]): WithRegistry