├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '5' 4 | - '4' 5 | - '0.12' 6 | - '0.10' 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) James Kyle (twitter.com/thejameskyle) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-stylish 2 | 3 | Make your React component style-able by all. 4 | 5 | > ***[See the blog post](https://medium.com/@thejameskyle/the-react-styling-problem-68440beceddf#.ygvbwgcio) 6 | > about "The React Styling Problem" and how this helps solve it.*** 7 | 8 | ## Guide 9 | 10 | React users have many different ways for styling their components. A mix between 11 | using good ole classNames and a million different ways of specifying inline 12 | styles. 13 | 14 | If you're trying to make a general purpose React Component and want to allow 15 | your users to style it however they please, you can use this tiny little module 16 | and forget about it. 17 | 18 | Basically you accept a `styles` prop, which is an object of either classNames or 19 | inline styles. Then you just pass the result over to your elements and move on. 20 | 21 | If you are using the 22 | [ES7 object spread operator](https://github.com/sebmarkbage/ecmascript-rest-spread) 23 | it's as simple as this: 24 | 25 | ```js 26 | import {getStyles} from 'react-stylish'; 27 | 28 | class MyComponent extends React.Component { 29 | render() { 30 | const {myElement} = getStyles(this.props.styles); 31 | return
; 32 | } 33 | } 34 | ``` 35 | 36 | > _If you are using Babel with the React preset, this should just work out of 37 | > the box without any additional setup._ 38 | 39 | If you are not using the spread operator you can use: 40 | 41 | ```js 42 | import {getStyles} from 'react-stylish'; 43 | 44 | class MyComponent extends React.Component { 45 | render() { 46 | const {myElement} = getStyles(this.props.styles); 47 | return
; 48 | } 49 | } 50 | ``` 51 | 52 | Don't forget about validating `PropTypes`! You can accept an object with any 53 | keys or you can specify the exact keys you want to allow. 54 | 55 | ```js 56 | import {PropType} from 'react-stylish'; 57 | 58 | class MyComponent extends React.Component { 59 | static propTypes = { 60 | // this will accept any keys: 61 | styles: PropType 62 | 63 | // or if you want to validate the exact keys to accept: 64 | styles: PropType.only(['myElement', 'otherElement']) 65 | 66 | // and if you want to make it required: 67 | styles: PropType.only(['myElement', 'otherElement']).isRequired 68 | }; 69 | } 70 | ``` 71 | 72 | ## Install 73 | 74 | ``` 75 | $ npm install --save react-stylish 76 | ``` 77 | 78 | ## Usage 79 | 80 | Setup your component like this: 81 | 82 | ```js 83 | import React from 'react'; 84 | import {getStyles, PropType} from 'react-stylish'; 85 | 86 | export class MyComponent extends React.Component { 87 | static propTypes = { 88 | styles: PropType.only(['foo', 'bar']).isRequired 89 | }; 90 | 91 | render() { 92 | const styles = getStyles(this.props.styles); 93 | return ( 94 |
95 |
96 | {this.props.children} 97 |
98 |
99 | ); 100 | } 101 | } 102 | ``` 103 | 104 | and users will consume it like this: 105 | 106 | ```js 107 | import MyComponent from 'my-component'; 108 | 109 | export default class CustomComponent extends React.Component { 110 | render() { 111 | return ( 112 | 119 | ); 120 | } 121 | } 122 | ``` 123 | 124 | ## License 125 | 126 | MIT © [James Kyle](http://twitter.com/thejameskyle) 127 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var PropTypes = React.PropTypes; 3 | 4 | var BasePropType = PropTypes.oneOfType([ 5 | PropTypes.string, 6 | PropTypes.object 7 | ]).isRequired; 8 | 9 | exports.PropType = PropTypes.objectOf(BasePropType); 10 | exports.PropType.only = function (keys) { 11 | var shape = {}; 12 | 13 | for (var i = 0; i < keys.length; i++) { 14 | shape[keys[i]] = BasePropType; 15 | } 16 | 17 | return PropTypes.shape(shape); 18 | }; 19 | 20 | exports.getStyles = function (styles) { 21 | var result = {}; 22 | var val; 23 | 24 | for (var key in styles) { 25 | if (styles.hasOwnProperty(key)) { 26 | val = styles[key]; 27 | result[key] = typeof val === 'string' ? {className: val} : {style: val}; 28 | } 29 | } 30 | 31 | return result; 32 | }; 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-stylish", 3 | "version": "1.0.0", 4 | "description": "Make your React component style-able by all.", 5 | "license": "MIT", 6 | "repository": "thejameskyle/react-stylish", 7 | "author": { 8 | "name": "James Kyle", 9 | "email": "me@thejameskyle.com", 10 | "url": "twitter.com/thejameskyle" 11 | }, 12 | "scripts": { 13 | "test": "ava" 14 | }, 15 | "files": [ 16 | "index.js" 17 | ], 18 | "keywords": [ 19 | "react", 20 | "style", 21 | "className", 22 | "component", 23 | "inline styles" 24 | ], 25 | "dependencies": { 26 | "react": "^0.14.0" 27 | }, 28 | "devDependencies": { 29 | "ava": "^0.8.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import {getStyles, PropType} from './'; 3 | 4 | test('getStyles', t => { 5 | const result = getStyles({ 6 | foo: 'className', 7 | bar: {display: 'block'} 8 | }); 9 | 10 | t.same(result, { 11 | foo: {className: 'className'}, 12 | bar: {style: {display: 'block'}} 13 | }); 14 | }); 15 | --------------------------------------------------------------------------------