bemto-components
Advanced tools
Comparing version 1.0.0 to 1.1.0
# `bemto-components` changelog | ||
## v1.1.0 (2017-10-30) | ||
- Added a basic way to create elements of the blocks. | ||
- Added a basic classNames/id parser to the tagString argument. | ||
- Fixed a rogue modifier whenever there was a single pregenerated className. | ||
- Fixed unneeded rendering of props started with underscore as attributes in React 16. | ||
- Added basic tests using jest ([#7](https://github.com/kizu/bemto-components/pull/7), thanks to [@SevInf](https://github.com/SevInf)). | ||
## v1.0.0 (2017-10-17) | ||
@@ -4,0 +12,0 @@ |
const React = require('react'); | ||
const modifyClassNames = function(classNames, modifiers) { | ||
return classNames + ' ' + classNames.split(' ').map(className => modifiers.map(modifier => className + modifier).join(' ')).join(' ').trim(); | ||
return (classNames + ' ' + classNames.trim().split(/\s+/).map(className => modifiers.map(modifier => className + modifier).join(' ')).join(' ')).trim(); | ||
}; | ||
const createElemClassNames = function(classNames, elemNames) { | ||
return (classNames.trim().split(/\s+/).map(className => elemNames.map(elemName => className + '__' + elemName).join(' ')).join(' ')).trim(); | ||
}; | ||
const gatherModifiers = function(props) { | ||
return Object.keys(props).filter(prop => props[prop] && prop[0] === '_').map(key => typeof props[key] === 'string' ? `${key}_${props[key]}` : key ); | ||
return Object.keys(props).filter(prop => props[prop] && prop[0] === '_' && prop[1] !== '_').map(key => typeof props[key] === 'string' ? `${key}_${props[key]}` : key ); | ||
}; | ||
const bemto = function(tagName) { | ||
return class bemtoTag extends React.Component { | ||
const parseTagString = function(tagString) { | ||
const result = {}; | ||
const parsedTagString = typeof tagString === 'string' && tagString.match(/^([^\.\#]*)((?:[\.\#][^\.\#]+)*)$/); | ||
result.tag = parsedTagString[1] || (typeof tagString === 'string' ? 'div' : tagString); | ||
result.classNames = (parsedTagString[2] && parsedTagString[2].replace(/\#[^\#\.]+/g, id => result.id ? '' : (result.id = id.replace('#', '')) && '') || '').replace(/\./g, ' '); | ||
return result; | ||
}; | ||
const bemto = function(tagString) { | ||
const parsedBlockTagString = parseTagString(tagString); | ||
const bemtoFactory = class bemtoTag extends React.Component { | ||
render(){ | ||
const TagName = tagName || 'div'; | ||
const elem = this.props.__BemtoElem; | ||
const parsedTagString = elem ? elem.parsedTagString : parsedBlockTagString; | ||
const props = {}; | ||
for (var key in this.props) { | ||
props[key] = this.props[key]; | ||
for (var key in (elem && elem.props || this.props)) { | ||
if (!(typeof parsedTagString.tag === 'string' && key[0] === '_') && key !== 'children') { | ||
props[key] = (elem && elem.props || this.props)[key]; | ||
} | ||
} | ||
props.className = modifyClassNames(props.className, gatherModifiers(props)) | ||
return React.createElement(TagName, props, this.props.children); | ||
if (parsedTagString.id && !props.id) { | ||
props.id = parsedTagString.id; | ||
} | ||
if (elem) { | ||
props.className = (props.className || '') + ' ' + createElemClassNames((this.props.className || '' + parsedBlockTagString.classNames), [elem.name]); | ||
} | ||
props.className = modifyClassNames((props.className || '') + parsedTagString.classNames, gatherModifiers(elem && elem.props || this.props)); | ||
return React.createElement(parsedTagString.tag, props, this.props.children); | ||
} | ||
}; | ||
bemtoFactory.elem = (elemName, tagString) => { | ||
return bemto.elem(bemtoFactory, elemName, tagString || ''); | ||
} | ||
return bemtoFactory; | ||
}; | ||
bemto.elem = function(block, elemName, tagString) { | ||
const parsedTagString = parseTagString(tagString); | ||
return class bemtoTag extends React.Component { | ||
render(){ | ||
const props = {}; | ||
props.__BemtoElem = { | ||
name: elemName, | ||
props: this.props, | ||
parsedTagString: parsedTagString | ||
}; | ||
return React.createElement(block, props, this.props.children); | ||
} | ||
} | ||
}; | ||
module.exports = bemto; |
{ | ||
"name": "bemto-components", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Smart components for using parts of BEM methodology with React", | ||
"main": "lib/index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "jest" | ||
}, | ||
@@ -26,4 +26,8 @@ "repository": { | ||
"dependencies": { | ||
"react": "15.4.1" | ||
"react": "15.6.2" | ||
}, | ||
"devDependencies": { | ||
"jest": "^21.2.1", | ||
"react-test-renderer": "15.6.2" | ||
} | ||
} |
124
Readme.md
@@ -1,15 +0,24 @@ | ||
# bemto-components <🍱> [WIP] | ||
# bemto-components <🍱> [WIP] [![Build Status][build]][build-link] [![NPM version][version]][version-link] | ||
Smart components for using parts of BEM methodology with React. Used best together with styled-components. | ||
[build]: https://travis-ci.org/kizu/bemto-components.png?branch=master | ||
[build-link]: https://travis-ci.org/kizu/bemto-components | ||
[version]: https://badge.fury.io/js/bemto-components.png | ||
[version-link]: https://www.npmjs.com/package/bemto-components | ||
Smart components for using parts of [BEM methodology](https://en.bem.info/methodology/quick-start/) with [React](https://reactjs.org/). Used best together with [styled-components](https://www.styled-components.com/). | ||
## What does it do? | ||
There are a lot of things `bemto-components` would do in the future, but for now here are two main features: | ||
There are a lot of things `bemto-components` would do in the future, but for now here are a few main features: | ||
1. `bemto-components` allow you to use BEM-style modifiers for your React components using the _modifier prop syntax. For ecample, if you'd do this (where the Foo is bemto-component): `<Foo _bar />`, each className of the Foo component would be duplicated with an addition of the `_bar` modifier. That allows you to use the BEM modifiers in your CSS (both any external, or using styled-components). | ||
2. _coming soon_ `bemto-components` would allow you to think less about handling your components' tag names by embracing some prop-based polymorphism. More on it when it would be ready! | ||
2. `bemto-components` gives you a way to easily create a component from a simple string that can contain an optional tag name (for now it defaults to `div` if omitted, but more on it coming, see the [3.]) and a bunch of classNames: `bemto('span.myClass1.myClass2')` would create a span component with the `myClass1 myClass2`, which would have all the other bemto features (like the applying of modifiers). | ||
2. `bemto-components` gives you a way to easily create BEM “Elements” for your components. | ||
3. _coming soon_ `bemto-components` would allow you to think less about handling your components' tag names by embracing some prop-based polymorphism. More on it when it would be ready! | ||
## Disclaimer | ||
@@ -30,2 +39,34 @@ | ||
``` jsx | ||
import bemto from 'bemto-components'; | ||
const Block = bemto('div.myBlock'); | ||
``` | ||
Usage: | ||
``` jsx | ||
<Block _mod> | ||
Hello | ||
</Block> | ||
``` | ||
This would output | ||
``` html | ||
<div class='myBlock myBlock_mod'>Hello</div> | ||
``` | ||
### Modifiers with string values | ||
Both boolean and string values are supported for modifiers: | ||
``` jsx | ||
<Block _mod1 _mod2='mod2value' /> | ||
``` | ||
### With styled-components | ||
Just pass a bemto-component inside styled-components: | ||
```jsx | ||
@@ -51,7 +92,78 @@ import bemto from 'bemto-components' | ||
More docs to come! | ||
## Example usage for elements | ||
For bemto-components you can call `.elem()` method to create an element: | ||
## Hint: you can do BEM elements without this lib | ||
``` jsx | ||
import bemto from 'bemto-components'; | ||
const Block = bemto('.myBlock'); | ||
Block.Element = Block.elem('myElement'); | ||
``` | ||
And then use it like this: | ||
``` jsx | ||
<Block> | ||
<Block.Element>Hello</Block.Element> | ||
</Block> | ||
``` | ||
Which would output | ||
``` html | ||
<div class='myBlock'><div class='myBlock__myElement'>Hello</div></div> | ||
``` | ||
### TagString for Elements | ||
Like with creation of Blocks, you can use a tagString, passing it as a second param when creating an element: | ||
``` jsx | ||
import bemto from 'bemto-components'; | ||
const Block = bemto('.myBlock'); | ||
Block.Element = Block.elem('myElement', 'span.extraElemClass'); | ||
``` | ||
Again, | ||
``` jsx | ||
<Block> | ||
<Block.Element>Hello</Block.Element> | ||
</Block> | ||
``` | ||
Would output | ||
``` html | ||
<div class='myBlock'><span class='myBlock__myElement extraElemClass'>Hello</span></div> | ||
``` | ||
### With styled-components | ||
As after wrapping with styled-component you would lose the `elem` method, there is an extra way to create elements: | ||
```jsx | ||
import bemto from 'bemto-components' | ||
const Block = styled(bemto())` | ||
background: red; | ||
&_mod { | ||
background: lime; | ||
} | ||
&__myElement { | ||
background: blue; | ||
} | ||
`); | ||
Block.Element = bemto.elem(Block, 'myElement', 'span.extraElemClass'); | ||
``` | ||
And there you'd even get the styled-components' names as block names. | ||
## Hint: if you have styled-components, you can emulate elements even without this lib: | ||
It is already possible to _kinda_ use Elements from BEM with react and/or styled components without adding anything extra: | ||
@@ -58,0 +170,0 @@ |
Sorry, the diff of this file is not supported yet
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
19265
10
182
0
192
2
+ Addedcreate-react-class@15.7.0(transitive)
+ Addedprop-types@15.8.1(transitive)
+ Addedreact@15.6.2(transitive)
+ Addedreact-is@16.13.1(transitive)
- Removedreact@15.4.1(transitive)
Updatedreact@15.6.2