├── .babelrc ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── mocha.config.js ├── package.json ├── src ├── class.js ├── decorator.js ├── dom.js ├── index.js ├── state.js └── utils.js ├── test ├── components.js ├── components.spec.js ├── index.spec.js ├── state.spec.js └── utils.spec.js └── winning.txt /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "react"], 3 | "plugins": [ 4 | "transform-decorators-legacy", 5 | "transform-class-properties", 6 | ["transform-runtime", { 7 | "polyfill": false, 8 | "regenerator": true 9 | }] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "sourceType": "module", 4 | "ecmaFeatures": { 5 | "arrowFunctions": true, 6 | "blockBindings": true, 7 | "destructuring": true, 8 | "regexYFlag": true, 9 | "regexUFlag": true, 10 | "templateStrings": true, 11 | "binaryLiterals": true, 12 | "octalLiterals": true, 13 | "unicodeCodePointEscapes": true, 14 | "defaultParams": true, 15 | "restParams": true, 16 | "forOf": true, 17 | "objectLiteralComputedProperties": true, 18 | "objectLiteralShorthandMethods": true, 19 | "objectLiteralShorthandProperties": true, 20 | "objectLiteralDuplicateProperties": true, 21 | "generators": true, 22 | "spread": true, 23 | "classes": true, 24 | "modules": true, 25 | "jsx": true, 26 | "globalReturn": true 27 | }, 28 | "rules": { 29 | "no-constant-condition": 2, 30 | "no-debugger": 2, 31 | "no-dupe-keys": 2, 32 | "no-empty": 2, 33 | "no-extra-boolean-cast": 2, 34 | "no-extra-semi": 2, 35 | "no-invalid-regexp": 2, 36 | "no-irregular-whitespace": 2, 37 | "no-regex-spaces": 2, 38 | "no-unreachable": 2, 39 | "use-isnan": 2, 40 | "valid-typeof": 2, 41 | "block-scoped-var": 0, 42 | // Uncomment when tracking down good refactor candidates 43 | // "complexity": [1, 2], 44 | "default-case": 2, 45 | "dot-notation": [2, {"allowKeywords": true, "allowPattern": ""}], 46 | "eqeqeq": 2, 47 | "guard-for-in": 2, 48 | "no-caller": 2, 49 | "no-else-return": 2, 50 | "no-eq-null": 2, 51 | "no-eval": 2, 52 | "no-extend-native": 2, 53 | "no-extra-bind": 2, 54 | "no-fallthrough": 2, 55 | "no-implied-eval": 2, 56 | "no-loop-func": 2, 57 | "no-new-wrappers": 2, 58 | "no-return-assign": 0, 59 | "no-script-url": 2, 60 | "no-self-compare": 2, 61 | "no-sequences": 2, 62 | "no-void": 2, 63 | "no-with": 2, 64 | "radix": 2, 65 | "vars-on-top": 2, 66 | "wrap-iife": [2, "outside"], 67 | "no-use-before-define": [2, "nofunc"], 68 | "indent": [2, 2], 69 | //"brace-style": [2, "1tbs", { "allowSingleLine": true }], 70 | "comma-spacing": [2, {"before": false, "after": true}], 71 | "consistent-this": [0, "self"], 72 | "eol-last": 2, 73 | "max-nested-callbacks": [2, 2], 74 | "no-mixed-spaces-and-tabs": 2, 75 | "semi-spacing": 2, 76 | "no-spaced-func": 2, 77 | "no-trailing-spaces": 2, 78 | "operator-assignment": [2, "always"], 79 | "quote-props": [2, "as-needed"], 80 | "quotes": [2, "single"], 81 | "semi": [2, "always"], 82 | "space-after-keywords": 2, 83 | "space-return-throw-case": 2, 84 | "spaced-comment": 0, 85 | "no-var": 2, 86 | "no-unused-vars": 0, 87 | "no-unused-expressions": 0, 88 | "new-cap": 0, // new-cap throws on Immutable.Map, etc 89 | "no-underscore-dangle": 0, 90 | "curly": 0, 91 | "yoda": 0, 92 | "no-multi-spaces": 0, 93 | "camelcase": 0, 94 | "key-spacing": 0 95 | }, 96 | "env": { 97 | "browser": true, 98 | "node": true, 99 | "mocha": true 100 | }, 101 | "globals": { 102 | "angular": false, 103 | "_": false 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | // OSX 2 | .DS_Store 3 | .Trashes 4 | 5 | // Node 6 | node_modules 7 | 8 | // Built files 9 | lib 10 | coverage 11 | *.min.js 12 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | // OSX 2 | .DS_Store 3 | .Trashes 4 | 5 | // Node 6 | node_modules 7 | 8 | // Built files 9 | coverage 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "iojs" 5 | 6 | branches: 7 | only: 8 | - master 9 | 10 | notifications: 11 | email: 12 | on_success: change 13 | on_failure: always 14 | 15 | script: 16 | - npm run -s lint 17 | - npm run -s test 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 InTurn 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 all 13 | 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 THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Classy logo 4 | 5 |

6 |

7 | 8 | npm version 9 | 10 | 11 | npm downloads 12 | 13 | 14 | build status 15 | 16 | 17 | dependency status 18 | 19 | 20 | devdependency status 21 | 22 |

23 |
24 | 25 | ### Table of Contents 26 | 27 | - [Install](#install) 28 | - [Getting Started](#getting-started) 29 | - [Usage](#usage) 30 | - [API](#api) 31 | 32 | Install 33 | ------- 34 | 35 | ##### `npm install react-classy` 36 | 37 | Getting Started 38 | --------------- 39 | 40 | Classy makes styling React components *composable*, *extensible*, and *simple*. 41 | Implementation requires only 3 steps: 42 | 43 | 0. Import `react-classy` into your React component module 44 | 0. Decorate your React component class with `@Classy`. 45 | 0. Assign a CSS string to a static `style` prop on your React component class. 46 | 47 | The styles defined on your React component will get automatically injected into 48 | the DOM right before your component mounts. Check out some examples of basic 49 | and advanced usage in the next section. 50 | 51 | Usage 52 | ----- 53 | 54 | ### Basic 55 | 56 | ```js 57 | import React, { Component } from 'react'; 58 | // Import Classy 59 | import Classy from 'react-classy'; 60 | 61 | // Decorate your component 62 | @Classy 63 | export default class Button extends Component { 64 | // Add your CSS styles 65 | static style = ` 66 | .button { 67 | background: blue; 68 | } 69 | ` 70 | render() { 71 | return ( 72 | 75 | ); 76 | } 77 | } 78 | 79 | ``` 80 | 81 | ### Advanced 82 | 83 | Classy is also highly customizable and supports asynchronous style 84 | rendering, custom middleware, and theming! In the next example, we'll 85 | demonstrate all of the aforementioned while creating a button that 86 | switches themes when clicked. 87 | 88 | ```js 89 | import React, { Component } from 'react'; 90 | // Import the decorator and utils modules 91 | import Classy, { Utils } from 'react-classy'; 92 | // CSS pre-processor 93 | import stylus from 'stylus'; 94 | 95 | @Classy({ 96 | 97 | // Makes Classy play nice with react-hot-loader :) 98 | hot: true, 99 | 100 | // Logs component css to console 101 | debug: true, 102 | 103 | // Will access specified prop to load component styles 104 | // instead of default `style` prop 105 | styleProp: 'stylus' 106 | 107 | }) 108 | export default class ToggleButton extends Component { 109 | 110 | render() { 111 | return