Skip to content

Commit

Permalink
Merge pull request #154 from ide/css-arrays
Browse files Browse the repository at this point in the history
RFC: Accept arrays of styles in css()
  • Loading branch information
jlfwong authored Oct 9, 2016
2 parents 1763b30 + b4e2a6b commit c6dc5f9
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 4 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,41 @@ const className = css(

This is possible because any falsey arguments will be ignored.

## Combining Styles

To combine styles, pass multiple styles or arrays of styles into `css()`. This is common when combining styles from an owner component:

```jsx
class App extends Component {
render() {
return <Marker styles={[styles.large, styles.red]} />;
}
}

class Marker extends Component {
render() {
// css() accepts styles, arrays of styles (including nested arrays),
// and falsy values including undefined.
return <div className={css(styles.marker, this.props.styles)} />;
}
}

const styles = StyleSheet.create({
red: {
backgroundColor: 'red'
},

large: {
height: 20,
width: 20
},

marker: {
backgroundColor: 'blue'
}
};
```
## Server-side rendering
To perform server-side rendering, make a call to `StyleSheetServer.renderStatic`, which takes a callback. Do your rendering inside of the callback and return the generated HTML. All of the calls to `css()` inside of the callback will be collected and the generated css as well as the generated HTML will be returned.
Expand Down
9 changes: 6 additions & 3 deletions src/inject.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import asap from 'asap';

import {generateCSS} from './generate';
import {hashObject} from './util';
import {flattenDeep, hashObject} from './util';

// The current <style> tag we are inserting into, or null if we haven't
// inserted anything yet. We could find this each time using
Expand Down Expand Up @@ -189,10 +189,13 @@ export const addRenderedClassNames = (classNames) => {
*
* @param {boolean} useImportant If true, will append !important to generated
* CSS output. e.g. {color: red} -> "color: red !important".
* @param {Object[]} styleDefinitions style definition objects as returned as
* properties of the return value of StyleSheet.create().
* @param {(Object|Object[])[]} styleDefinitions style definition objects, or
* arbitrarily nested arrays of them, as returned as properties of the
* return value of StyleSheet.create().
*/
export const injectAndGetClassName = (useImportant, styleDefinitions) => {
styleDefinitions = flattenDeep(styleDefinitions);

// Filter out falsy values from the input, to allow for
// `css(a, test && c)`
const validDefinitions = styleDefinitions.filter((def) => def);
Expand Down
3 changes: 3 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export const mapObj = (obj, fn) => pairsToObject(objectToPairs(obj).map(fn))
// [[A], [B, C, [D]]] -> [A, B, C, [D]]
export const flatten = (list) => list.reduce((memo, x) => memo.concat(x), []);

export const flattenDeep = (list) =>
list.reduce((memo, x) => memo.concat(Array.isArray(x) ? flattenDeep(x) : x), []);

const UPPERCASE_RE = /([A-Z])/g;
const MS_RE = /^ms-/;

Expand Down
17 changes: 17 additions & 0 deletions tests/index_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,23 @@ describe('css', () => {
assert.equal(css(sheet.red), css(false, sheet.red));
});

it('accepts arrays of styles', () => {
const sheet = StyleSheet.create({
red: {
color: 'red',
},

blue: {
color: 'blue'
}
});

assert.equal(css(sheet.red, sheet.blue), css([sheet.red, sheet.blue]));
assert.equal(css(sheet.red, sheet.blue), css(sheet.red, [sheet.blue]));
assert.equal(css(sheet.red, sheet.blue), css([sheet.red, [sheet.blue]]));
assert.equal(css(sheet.red), css(false, [null, false, sheet.red]));
});

it('succeeds for with empty args', () => {
assert(css() != null);
assert(css(false) != null);
Expand Down
10 changes: 9 additions & 1 deletion tests/util_test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import {assert} from 'chai';

import {recursiveMerge} from '../src/util.js';
import {flattenDeep, recursiveMerge} from '../src/util.js';

describe('Utils', () => {
describe('flattenDeep', () => {
it('flattens arrays at any level', () => {
assert.deepEqual(
flattenDeep([[1, [2, 3, []]], 4, [[5], [6, [7]]]]),
[1, 2, 3, 4, 5, 6, 7]);
});
});

describe('recursiveMerge', () => {
it('merges two objects', () => {
assert.deepEqual(
Expand Down

0 comments on commit c6dc5f9

Please sign in to comment.