Skip to content

Commit

Permalink
[changed] Renamed constants to styleMaps and added styleMaps.addStyle()
Browse files Browse the repository at this point in the history
  • Loading branch information
Trevor Robinson committed Apr 17, 2015
1 parent 527e21f commit e1c95b3
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 18 deletions.
18 changes: 9 additions & 9 deletions src/BootstrapMixin.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import React from 'react';
import constants from './constants';
import styleMaps from './styleMaps';
import CustomPropTypes from './utils/CustomPropTypes';

const BootstrapMixin = {
propTypes: {
bsClass: React.PropTypes.oneOf(Object.keys(constants.CLASSES)),
bsStyle: React.PropTypes.oneOf(Object.keys(constants.STYLES)),
bsSize: React.PropTypes.oneOf(Object.keys(constants.SIZES))
bsClass: CustomPropTypes.keyOf(styleMaps.CLASSES),
bsStyle: CustomPropTypes.keyOf(styleMaps.STYLES),
bsSize: CustomPropTypes.keyOf(styleMaps.SIZES)
},

getBsClassSet() {
let classes = {};

let bsClass = this.props.bsClass && constants.CLASSES[this.props.bsClass];
let bsClass = this.props.bsClass && styleMaps.CLASSES[this.props.bsClass];
if (bsClass) {
classes[bsClass] = true;

let prefix = bsClass + '-';

let bsSize = this.props.bsSize && constants.SIZES[this.props.bsSize];
let bsSize = this.props.bsSize && styleMaps.SIZES[this.props.bsSize];
if (bsSize) {
classes[prefix + bsSize] = true;
}

let bsStyle = this.props.bsStyle && constants.STYLES[this.props.bsStyle];
let bsStyle = this.props.bsStyle && styleMaps.STYLES[this.props.bsStyle];
if (this.props.bsStyle) {
classes[prefix + bsStyle] = true;
}
Expand All @@ -32,7 +32,7 @@ const BootstrapMixin = {
},

prefixClass(subClass) {
return constants.CLASSES[this.props.bsClass] + '-' + subClass;
return styleMaps.CLASSES[this.props.bsClass] + '-' + subClass;
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/Col.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import classNames from 'classnames';
import constants from './constants';
import styleMaps from './styleMaps';

const Col = React.createClass({
propTypes: {
Expand Down Expand Up @@ -33,8 +33,8 @@ const Col = React.createClass({
let ComponentClass = this.props.componentClass;
let classes = {};

Object.keys(constants.SIZES).forEach(function (key) {
let size = constants.SIZES[key];
Object.keys(styleMaps.SIZES).forEach(function (key) {
let size = styleMaps.SIZES[key];
let prop = size;
let classPart = size + '-';

Expand Down
4 changes: 2 additions & 2 deletions src/Glyphicon.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import constants from './constants';
import styleMaps from './styleMaps';

const Glyphicon = React.createClass({
mixins: [BootstrapMixin],

propTypes: {
glyph: React.PropTypes.oneOf(constants.GLYPHS).isRequired
glyph: React.PropTypes.oneOf(styleMaps.GLYPHS).isRequired
},

getDefaultProps() {
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import Table from './Table';
import TabPane from './TabPane';
import Tooltip from './Tooltip';
import Well from './Well';
import constants from './constants';
import styleMaps from './styleMaps';

export default {
Accordion,
Expand Down Expand Up @@ -99,5 +99,5 @@ export default {
TabPane,
Tooltip,
Well,
constants
styleMaps
};
7 changes: 6 additions & 1 deletion src/constants.js → src/styleMaps.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default {
const styleMaps = {
CLASSES: {
'alert': 'alert',
'button': 'btn',
Expand Down Expand Up @@ -31,6 +31,9 @@ export default {
'tabs': 'tabs',
'pills': 'pills'
},
addStyle: function(name) {
styleMaps.STYLES[name] = name;
},
SIZES: {
'large': 'lg',
'medium': 'md',
Expand Down Expand Up @@ -299,3 +302,5 @@ export default {
'menu-up'
]
};

export default styleMaps;
25 changes: 24 additions & 1 deletion src/utils/CustomPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@ let CustomPropTypes = {
* @param componentName
* @returns {Error|undefined}
*/
mountable: createMountableChecker()
mountable: createMountableChecker(),
/**
* Checks whether a prop matches a key of an associated object
*
* @param props
* @param propName
* @param componentName
* @returns {Error|undefined}
*/
keyOf: createKeyOfChecker
};

/**
Expand Down Expand Up @@ -57,4 +66,18 @@ function createMountableChecker() {
return createChainableTypeChecker(validate);
}

function createKeyOfChecker(obj) {
function validate(props, propName, componentName) {
let propValue = props[propName];
if (!obj.hasOwnProperty(propValue)) {
let valuesString = JSON.stringify(Object.keys(obj));
return new Error(
`Invalid prop '${propName}' of value '${propValue}' ` +
`supplied to '${componentName}', expected one of ${valuesString}.`
);
}
}
return createChainableTypeChecker(validate);
}

export default CustomPropTypes;
11 changes: 11 additions & 0 deletions test/BootstrapMixinSpec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import BootstrapMixin from '../src/BootstrapMixin';
import styleMaps from '../src/styleMaps';

let Component;

Expand Down Expand Up @@ -195,5 +196,15 @@ describe('BootstrapMixin', function () {
);
assert.equal(instance.prefixClass('title'), 'btn-title');
});

it('should return "btn btn-wacky"', function () {
styleMaps.addStyle('wacky');
let instance = ReactTestUtils.renderIntoDocument(
<Component bsClass='button' bsStyle='wacky'>
content
</Component>
);
assert.deepEqual(instance.getBsClassSet(), {'btn': true, 'btn-wacky': true});
});
});
});
22 changes: 22 additions & 0 deletions test/CustomPropTypesSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,26 @@ describe('CustomPropTypes', function () {
assert.isUndefined(validate(ReactTestUtils.renderIntoDocument(<div />)));
});
});

describe('keyOf', function () {
let obj = {'foo': 1};
function validate(prop) {
return CustomPropTypes.keyOf(obj)({p: prop}, 'p', 'Component');
}
function validateRequired(prop) {
return CustomPropTypes.keyOf(obj).isRequired({p: prop}, 'p', 'Component');
}

it('Should return error with non-key values', function() {
assert.instanceOf(validateRequired(), Error);
assert.instanceOf(validateRequired(null), Error);
assert.instanceOf(validate('bar'), Error);
});
it('Should return undefined with key values', function() {
assert.isUndefined(validate());
assert.isUndefined(validate('foo'));
obj.bar = 2;
assert.isUndefined(validate('bar'));
});
});
});

0 comments on commit e1c95b3

Please sign in to comment.