Skip to content
This repository has been archived by the owner on Jun 4, 2020. It is now read-only.

Commit

Permalink
feat(styles): add styles and children support
Browse files Browse the repository at this point in the history
  • Loading branch information
danielwerthen committed Jan 18, 2016
2 parents 3299939 + 64caa9d commit 0124078
Show file tree
Hide file tree
Showing 7 changed files with 406 additions and 160 deletions.
71 changes: 70 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ Compose React components with a functional api
Example api usage:

import { compose } from 'react-compose';

const constantProper = {
age: 15,
};

const dynamicProper = props => {
return {
children: `The cat is ${props.age} years old`,
};
};

const Cat = compose(constantProper, dynamicProper)('p');

// => <p>The cat is 15 years old</p>;

Specialized style composing

import { compose, styles } from 'react-compose';

const constantStyle = {
background: 'red',
Expand All @@ -12,8 +30,59 @@ Example api usage:
display: 'none',
});

const Component = compose(constantStyle, dynamicStyle)('p');
const Component = compose(styles(constantStyle, dynamicStyle))('p');

return (props) => {
return <Component isActive={false}>Some text</Component>;
};

Stacking custom components

import { compose } from 'react-compose';

const Cat = props => {
return <p>The cat is {props.age} years old</p>;
};

const injectAge = {
age: 5,
};

const Composed = compose(injectAge)(Cat);

// => <p>The cat is 5 years old</p>


Composing complex children values

import { compose, children } from 'react-compose';

const AgeInfo = props => {
return <p>Age: {props.age} years</p>;
};

const LengthInfo = props => {
return <p>Length: {props.length} cm</p>;
};

const HeightInfo = props => {
return <p>Height: {props.height} cm</p>;
};

const Info = compose(children(AgeInfo, LengthInfo, HeightInfo))('div');

const dogData = {
age: 5,
length: 250,
height: 150,
};

const DogInfo = compose(dogData)(Info);

// => <div>
// <p>Age: 5</p>
// <p>Length: 250</p>
// <p>Height: 150</p>
// </div>


130 changes: 102 additions & 28 deletions lib/__tests__/compose-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,41 @@ jest.autoMockOff();

var _ = require('lodash');

var compileStylers = require('../index').compileStylers;
var compilePropers = require('../index').compilePropers;
var optimize = require('../index').optimize;
var applyFunctor = require('../index').applyFunctor;
var compose = require('../index').compose;
var styles = require('../index').styles;
var children = require('../index').children;

describe('compileStylers', function () {
it('should merge stylers', function () {
var res = compileStylers({
background: 'blue'
}, {
color: 'red'
}, function () {
return { width: 400 };
});
expect(res.constant).toEqual({
background: 'blue',
color: 'red'
});
expect(res.dynamic.length).toEqual(1);
});
});
describe('compilePropers', function () {
describe('optimize', function () {
it('should merge propers', function () {
var res = compilePropers({
var res = optimize({
propA: 'alpha'
}, {
propB: 2
}, function () {
return { width: 400 };
}, function () {
return { width: 400 };
}, 'div');
});
expect(res.constant).toEqual({
propA: 'alpha',
propB: 2
});
expect(res.dynamic.length).toEqual(2);
expect(res.Component).toEqual('div');
});
it('should merge propers ignore constants after dynamics', function () {
var res = optimize({
propA: 'alpha'
}, function () {
return { width: 400 };
}, { propB: 2 }, function () {
return { width: 400 };
});
expect(res.constant).toEqual({
propA: 'alpha'
});
expect(res.dynamic.length).toEqual(3);
});
});

Expand Down Expand Up @@ -125,26 +122,103 @@ var findTag = function findTag(comp, tag) {
};

describe('Compose', function () {
var mapPropToStyleFunctor = function mapPropToStyleFunctor(propKey, styleKey) {
var mapPropToKeyFunctor = function mapPropToKeyFunctor(propKey, key) {
return function (props) {
return _defineProperty({}, styleKey, props[propKey]);
return _defineProperty({}, key, props[propKey]);
};
};
it('should produce a valid component', function () {
var Compo = compose({ background: 'blue' })({ children: 'boo' }, 'p');
var Compo = compose({ background: 'blue' }, { children: 'boo' })('p');
var doc = renderInto(Compo);
var para = findTag(doc, 'p');
expect(para.style.background).toEqual('blue');
expect(para.props.background).toEqual('blue');
});

it('should pass fed props into style functors', function () {
var Compo = compose({ background: 'blue' }, mapPropToStyleFunctor('strength', 'fontSize'))({ strength: '400px' }, 'p');
var Compo = compose({ background: 'blue', strength: '400px' }, mapPropToKeyFunctor('strength', 'fontSize'))('p');
var doc = renderInto(function () {
return React.createElement(Compo, { style: { color: 'white' } });
});
var para = findTag(doc, 'p');
expect(para.props.background).toEqual('blue');
expect(para.style.color).toEqual('white');
expect(para.props.fontSize).toEqual('400px');
});
});

describe('Styles', function () {
var pToK = function pToK(propKey, key) {
return function (props) {
return _defineProperty({}, key, props[propKey]);
};
};
it('should produce a valid component', function () {
var Compo = compose(styles({ background: 'blue' }, { color: 'white' }))('p');
var doc = renderInto(Compo);
var para = findTag(doc, 'p');
expect(para.style.background).toEqual('blue');
expect(para.style.color).toEqual('white');
});
it('should produce a valid component with two separate styles', function () {
var Compo = compose(styles({ background: 'blue' }), styles({ color: 'white' }))('p');
var doc = renderInto(Compo);
var para = findTag(doc, 'p');
expect(para.style.background).toEqual('blue');
expect(para.style.color).toEqual('white');
expect(para.style.fontSize).toEqual('400px');
});
it('should produce a valid component with two dynamic stylers', function () {
var Compo = compose({ strength: 5, weight: 'normal' }, styles(pToK('strength', 'fontSize'), pToK('weight', 'fontWeight')))('p');
var doc = renderInto(Compo);
var para = findTag(doc, 'p');
expect(para.style.fontSize).toEqual('5px');
expect(para.style.fontWeight).toEqual('normal');
});
it('should produce a valid component with composite dynamic stylers', function () {
var fontStyle = {
fontSize: '5px',
fontWeight: 'normal'
};
var colorStyle = {
color: 'blue',
backgroundColor: 'white'
};
var compositeStyle = function compositeStyle() {
return [fontStyle, colorStyle];
};
var Compo = compose(styles(compositeStyle))('p');
var doc = renderInto(Compo);
var para = findTag(doc, 'p');
expect(para.style.fontSize).toEqual('5px');
expect(para.style.fontWeight).toEqual('normal');
});
it('should produce a valid component with composite multilayer dynamic stylers', function () {
var fontStyle = pToK('strength', 'fontSize');
var colorStyle = {
color: 'blue',
backgroundColor: 'white'
};
var compositeStyle = function compositeStyle() {
return [fontStyle, colorStyle];
};
var Compo = compose({ strength: '5' }, styles(compositeStyle))('p');
var doc = renderInto(Compo);
var para = findTag(doc, 'p');
expect(para.style.fontSize).toEqual('5px');
});
});

describe('Children', function () {
it('should produce a valid component', function () {
var Alpha = function Alpha(props) {
return React.createElement(
'span',
null,
'The cat is ' + props.feeling
);
};
var Compo = compose({ feeling: 'angry' }, children(Alpha))('p');
var doc = renderInto(Compo);
var para = findTag(doc, 'span');
expect(para.innerHTML).toEqual('The cat is angry too');
});
});
26 changes: 14 additions & 12 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.plugin = exports.parseSuperProps = exports.composeComponent = exports.exposeContextTypes = undefined;
exports.plugin = exports.renderChild = exports.composeComponent = exports.exposeContextTypes = undefined;

var _lodash = require('lodash');

Expand Down Expand Up @@ -61,21 +61,23 @@ var exposeContextTypes = exports.exposeContextTypes = configurable('exposeContex
var merge = function merge(arr) {
return _lodash2.default.assign.apply(_lodash2.default, [{}].concat(_toConsumableArray(arr)));
};
var defaultComposeComponent = function defaultComposeComponent(Component, styles, props) {
return _react2.default.createElement(Component, _extends({ style: merge(styles) }, props));
};
var composeComponent = exports.composeComponent = configurable('composeComponent', defaultComposeComponent);
var defaultComposeComponent = function defaultComposeComponent(Component, props) {
var _props$styles = props.styles;
var styles = _props$styles === undefined ? [] : _props$styles;
var _props$style = props.style;
var style = _props$style === undefined ? {} : _props$style;

var defaultParseSuperProps = function defaultParseSuperProps(_ref) {
var style = _ref.style;
var rest = _objectWithoutProperties(props, ['styles', 'style']);

var props = _objectWithoutProperties(_ref, ['style']);
return _react2.default.createElement(Component, _extends({ style: merge([style].concat(styles)) }, rest));
};
var composeComponent = exports.composeComponent = configurable('composeComponent', defaultComposeComponent);

return {
styles: [style],
props: props
var defaultRenderChild = function defaultRenderChild(props) {
return function (Child, index) {
return _react2.default.createElement(Child, _extends({}, props, { key: (Child.displayName || '') + index }));
};
};
var parseSuperProps = exports.parseSuperProps = configurable('parseSuperProps', defaultParseSuperProps);
var renderChild = exports.renderChild = configurable('renderChild', defaultRenderChild);

exports.plugin = plugin;
Loading

0 comments on commit 0124078

Please sign in to comment.