classnames
Advanced tools
Comparing version 2.1.5 to 2.2.0
{ | ||
"name": "classnames", | ||
"version": "2.1.5", | ||
"version": "2.2.0", | ||
"description": "A simple utility for conditionally joining classNames together", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
# Changelog | ||
## v2.2.0 / 2015-10-18 | ||
* added a new `bind` variant for use with [css-modules](https://github.com/css-modules/css-modules) and similar abstractions, thanks to [Kirill Yakovenko](https://github.com/blia) | ||
## v2.1.5 / 2015-09-30 | ||
@@ -4,0 +8,0 @@ |
{ | ||
"name": "classnames", | ||
"version": "2.1.5", | ||
"version": "2.2.0", | ||
"description": "A simple utility for conditionally joining classNames together", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -40,2 +40,3 @@ Classnames | ||
classNames('foo', { bar: true }); // => 'foo bar' | ||
classNames({ 'foo-bar': true }); // => 'foo-bar' | ||
classNames({ foo: true }, { bar: true }); // => 'foo bar' | ||
@@ -58,2 +59,48 @@ classNames({ foo: true, bar: true }); // => 'foo bar' | ||
### Usage with React.js | ||
This package is the official replacement for `classSet`, which was originally shipped in the React.js Addons bundle. | ||
One of its primary use cases is to make dynamic and conditional className props simpler to work with (especially more so than conditional string manipulation). So where you may have the following code to generate a `className` prop for a `<button>` in React: | ||
```js | ||
var Button = React.createClass({ | ||
// ... | ||
render () { | ||
var btnClass = 'btn'; | ||
if (this.state.isPressed) btnClass += ' btn-pressed'; | ||
else if (this.state.isHovered) buttonClass += ' btn-over'; | ||
return <button className={btnClass}>{this.props.label}</button>; | ||
} | ||
}); | ||
``` | ||
You can express the conditional classes more simply as an object: | ||
```js | ||
var classNames = require('classnames'); | ||
var Button = React.createClass({ | ||
// ... | ||
render () { | ||
var btnClass = classNames({ | ||
'btn': true, | ||
'btn-pressed': this.state.isPressed, | ||
'btn-over': !this.state.isPressed && this.state.isHovered | ||
}); | ||
return <button className={btnClass}>{this.props.label}</button>; | ||
} | ||
}); | ||
``` | ||
Because you can mix together object, array and string arguments, supporting optional className props is also simpler as only truthy arguments get included in the result: | ||
```js | ||
var btnClass = classNames('btn', this.props.className, { | ||
'btn-pressed': this.state.isPressed, | ||
'btn-over': !this.state.isPressed && this.state.isHovered | ||
}); | ||
``` | ||
### Alternate `dedupe` version | ||
@@ -63,5 +110,9 @@ | ||
For example: | ||
This version is slower (about 10x) so it is offered as an opt-in. | ||
To use the dedupe version with node, browserify or webpack: | ||
```js | ||
var classNames = require('classnames/dedupe'); | ||
classNames('foo', 'foo', 'bar'); // => 'foo bar' | ||
@@ -71,13 +122,24 @@ classNames('foo', { foo: false, bar: true }); // => 'bar' | ||
This version is slower (about 10x) so it is offered as an opt-in. | ||
For standalone (global / AMD) use, include `dedupe.js` in a `<script>` tag on your page. | ||
To use the dedupe version with node, browserify or webpack: | ||
### Alternate `bind` version (for [css-modules](https://github.com/css-modules/css-modules)) | ||
If you are using [css-modules](https://github.com/css-modules/css-modules), or a similar approach to abstract class "names" and the real `className` values that are actually output to the DOM, you may want to use the `bind` variant. | ||
```js | ||
var classNames = require('classnames/dedupe'); | ||
var classNames = require('classnames/bind'); | ||
var styles = { | ||
foo: 'abc', | ||
bar: 'def', | ||
baz: 'xyz' | ||
} | ||
var cx = classNames.bind(styles); | ||
var className = cx('foo', ['bar'], { baz: true }); // => "abc def xyz" | ||
``` | ||
Or for standalone (global / AMD) use, include `dedupe.js` in a `<script>` tag on your page. | ||
## Polyfills needed to support older browsers | ||
@@ -84,0 +146,0 @@ |
@@ -7,57 +7,57 @@ /* global describe, it */ | ||
describe('classNames', function () { | ||
it('keeps object keys with truthy values', function () { | ||
assert.equal(classNames({ | ||
a: true, | ||
b: false, | ||
c: 0, | ||
d: null, | ||
e: undefined, | ||
f: 1 | ||
}), 'a f'); | ||
}); | ||
it('keeps object keys with truthy values', function () { | ||
assert.equal(classNames({ | ||
a: true, | ||
b: false, | ||
c: 0, | ||
d: null, | ||
e: undefined, | ||
f: 1 | ||
}), 'a f'); | ||
}); | ||
it('joins arrays of class names and ignore falsy values', function () { | ||
assert.equal(classNames('a', 0, null, undefined, true, 1, 'b'), 'a 1 b'); | ||
}); | ||
it('joins arrays of class names and ignore falsy values', function () { | ||
assert.equal(classNames('a', 0, null, undefined, true, 1, 'b'), 'a 1 b'); | ||
}); | ||
it('supports heterogenous arguments', function () { | ||
assert.equal(classNames({a: true}, 'b', 0), 'a b'); | ||
}); | ||
it('supports heterogenous arguments', function () { | ||
assert.equal(classNames({a: true}, 'b', 0), 'a b'); | ||
}); | ||
it('should be trimmed', function () { | ||
assert.equal(classNames('', 'b', {}, ''), 'b'); | ||
}); | ||
it('should be trimmed', function () { | ||
assert.equal(classNames('', 'b', {}, ''), 'b'); | ||
}); | ||
it('returns an empty string for an empty configuration', function () { | ||
assert.equal(classNames({}), ''); | ||
}); | ||
it('returns an empty string for an empty configuration', function () { | ||
assert.equal(classNames({}), ''); | ||
}); | ||
it('supports an array of class names', function () { | ||
assert.equal(classNames(['a', 'b']), 'a b'); | ||
}); | ||
it('supports an array of class names', function () { | ||
assert.equal(classNames(['a', 'b']), 'a b'); | ||
}); | ||
it('joins array arguments with string arguments', function () { | ||
assert.equal(classNames(['a', 'b'], 'c'), 'a b c'); | ||
assert.equal(classNames('c', ['a', 'b']), 'c a b'); | ||
}); | ||
it('joins array arguments with string arguments', function () { | ||
assert.equal(classNames(['a', 'b'], 'c'), 'a b c'); | ||
assert.equal(classNames('c', ['a', 'b']), 'c a b'); | ||
}); | ||
it('handles multiple array arguments', function () { | ||
assert.equal(classNames(['a', 'b'], ['c', 'd']), 'a b c d'); | ||
}); | ||
it('handles multiple array arguments', function () { | ||
assert.equal(classNames(['a', 'b'], ['c', 'd']), 'a b c d'); | ||
}); | ||
it('handles arrays that include falsy and true values', function () { | ||
assert.equal(classNames(['a', 0, null, undefined, false, true, 'b']), 'a b'); | ||
}); | ||
it('handles arrays that include falsy and true values', function () { | ||
assert.equal(classNames(['a', 0, null, undefined, false, true, 'b']), 'a b'); | ||
}); | ||
it('handles arrays that include arrays', function () { | ||
assert.equal(classNames(['a', ['b', 'c']]), 'a b c'); | ||
}); | ||
it('handles arrays that include arrays', function () { | ||
assert.equal(classNames(['a', ['b', 'c']]), 'a b c'); | ||
}); | ||
it('handles arrays that include objects', function () { | ||
assert.equal(classNames(['a', {b: true, c: false}]), 'a b'); | ||
}); | ||
it('handles arrays that include objects', function () { | ||
assert.equal(classNames(['a', {b: true, c: false}]), 'a b'); | ||
}); | ||
it('handles deep array recursion', function () { | ||
assert.equal(classNames(['a', ['b', ['c', {d: true}]]]), 'a b c d'); | ||
}); | ||
it('handles deep array recursion', function () { | ||
assert.equal(classNames(['a', ['b', ['c', {d: true}]]]), 'a b c d'); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26168
17
503
152