├── .eslintrc
├── .gitignore
├── .vscode
└── settings.json
├── README.md
├── examples
├── .babelrc
├── .eslintrc
├── .gitignore
├── README.md
├── index.html
├── package.json
├── server.js
└── src
│ ├── App.js
│ └── index.js
├── lib
├── StylesRendererProvider.js
├── VStyleDOMComponent.js
├── index.js
├── stylesRendererShape.js
└── withRenderStyles.js
└── package.json
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb-base/legacy",
3 | "rules": {
4 | "no-underscore-dangle": 0,
5 | "no-trailing-spaces": 0,
6 | "no-param-reassign": 0,
7 | "func-names": 0,
8 | "vars-on-top": 0
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | bundle.js
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.tabSize": 2,
3 | "editor.detectIndentation": false,
4 | "eslint.enable": true
5 | }
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-vstyle
2 |
3 | > React bindings for [VStyle](https://github.com/fdecampredon/vstyle)
4 |
5 |
6 | ## Install
7 | You can install react-vstyle through npm:
8 | ```
9 | npm install react-vstyle
10 | ```
11 |
12 | ## Usage
13 |
14 | ### StylesRendererProvider
15 |
16 | react-vstyle let you inject a VStyle `StylesRenderer` in the react context with the `StylesRendererProvider` component:
17 |
18 | ```javascript
19 | import React from 'react';
20 | import ReactDOM from 'react-dom';
21 | import { createStylesRenderer } from 'vstyle';
22 | import { StylesRendererProvider } from 'react-vstyle';
23 | import MyComponent from './myComponent';
24 |
25 | const stylesRenderer = createStylesRenderer();
26 | stylesRenderer.attach(document.getElementById('style'));
27 |
28 | ReactDOM.render(
29 |
30 |
31 | ,
32 | document.getElementById('root')
33 | );
34 | ```
35 |
36 | once you have injected your `StylesRenderer` into the context you can consume your styles in 2 ways :
37 |
38 | ## withRenderStyles
39 |
40 | `withRenderStyles` is an higher order component that will inject the `renderStyles`
41 | function of the `StylesRenderer` to the props of the wrapped component:
42 |
43 | ```javascript
44 | import React from 'react';
45 | import { StyleSheet } from 'vstyle';
46 | import { withRenderStyles } from 'react-vstyle';
47 |
48 | const styles = StyleSheet.create({
49 | button: {
50 | color: 'blue',
51 | },
52 | });
53 |
54 | function MyComponent({ renderStyles, styles: otherStyles }) {
55 | return ;
56 | }
57 |
58 | export default withRenderStyles(MyComponent)
59 | ```
60 |
61 | ## Native component injection
62 |
63 | Alternatively you can use the experimental `injectNativeComponent` function of react-vstyle,
64 | then you can drop your styles in the `styles` (notice the _s_) property of your DOM components:
65 |
66 | ```javascript
67 | import React from 'react';
68 | import ReactDOM from 'react-dom';
69 | import { createStylesRenderer } from 'vstyle';
70 | import { StylesRendererProvider, injectNativeComponent } from 'react-vstyle';
71 | import MyComponent from './myComponent';
72 |
73 | injectNativeComponent();
74 |
75 | const stylesRenderer = createStylesRenderer();
76 | stylesRenderer.attach(document.getElementById('style'));
77 |
78 | ReactDOM.render(
79 |
80 |
81 | ,
82 | document.getElementById('root')
83 | );
84 | ```
85 |
86 | ```javascript
87 | import React from 'react';
88 | import { StyleSheet } from 'vstyle';
89 | import { withRenderStyles } from 'react-vstyle';
90 |
91 | const styles = StyleSheet.create({
92 | button: {
93 | color: 'blue',
94 | },
95 | });
96 |
97 | export default function MyComponent({ styles: otherStyles }) {
98 | return ;
99 | }
100 | ```
101 |
--------------------------------------------------------------------------------
/examples/.babelrc:
--------------------------------------------------------------------------------
1 | { "presets": ["es2015", "react"] }
2 |
--------------------------------------------------------------------------------
/examples/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "no-trailing-spaces": 0,
5 | "no-param-reassign": 0,
6 | "func-names": 0,
7 | "vars-on-top": 0,
8 | "react/prop-types": 0
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/.gitignore:
--------------------------------------------------------------------------------
1 | bundle.js
2 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Example
2 |
3 | To run this example start by installing dependencies :
4 | ```
5 | npm install
6 | ```
7 |
8 | Then you can either run the client only example by excuting this script:
9 | ```
10 | npm run build
11 | ```
12 | Then open the `index.html` file in your favorite browser.
13 |
14 | You can also run the server-side rendered example by executing this script:
15 | ```
16 | npm start
17 | ```
18 | Then open your browser at http://localhost:3000 .
19 |
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "start": "babel-node server.js",
4 | "build": "browserify -d ./src/index.js > bundle.js"
5 | },
6 | "author": "",
7 | "license": "Apache-2.0",
8 | "devDependencies": {
9 | "babel-cli": "^6.9.0"
10 | },
11 | "dependencies": {
12 | "babel-preset-es2015": "^6.9.0",
13 | "babel-preset-react": "^6.5.0",
14 | "babelify": "^7.3.0",
15 | "browserify": "^13.0.1",
16 | "react": "^15.1.0",
17 | "react-dom": "^15.1.0",
18 | "serialize-javascript": "^1.2.0",
19 | "vstyle": "^0.1.2",
20 | "react-vstyle": "file:.."
21 | },
22 | "browserify": {
23 | "transform": [
24 | [
25 | "babelify"
26 | ]
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/server.js:
--------------------------------------------------------------------------------
1 | import http from 'http';
2 | import React from 'react';
3 | import ReactDOMServer from 'react-dom/server';
4 | import browserify from 'browserify';
5 | import serialize from 'serialize-javascript';
6 | import { createStylesRenderer } from 'vstyle';
7 | import { StylesRendererProvider, injectNativeComponent } from 'react-vstyle';
8 | import App from './src/App';
9 |
10 | injectNativeComponent();
11 |
12 | http.createServer((req, res) => {
13 | if (req.url === '/bundle.js') {
14 | res.setHeader('content-type', 'application/javascript');
15 | const b = browserify(`${__dirname}/src/index.js`).transform('babelify').bundle();
16 | b.pipe(res);
17 | } else {
18 | const stylesRenderer = createStylesRenderer();
19 | const markup = ReactDOMServer.renderToString(
20 |
21 |
22 |
23 | );
24 | const styles = stylesRenderer.renderToString();
25 | const rendererStates = stylesRenderer.serialize();
26 |
27 | res.writeHead(200, { 'Content-Type': 'text/html' });
28 | res.end(`
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ${markup}
37 |
40 |
41 |
42 |
43 | `);
44 | }
45 | }).listen(3000);
46 |
--------------------------------------------------------------------------------
/examples/src/App.js:
--------------------------------------------------------------------------------
1 | // this example has been taken from aphrodite: https://github.com/Khan/aphrodite
2 |
3 | import React from 'react';
4 | import { StyleSheet, registerPlugin } from 'vstyle';
5 | import defaultUnitPlugin from 'vstyle/lib/plugins/default-unit';
6 | import { withRenderStyles } from 'react-vstyle';
7 |
8 | registerPlugin(defaultUnitPlugin());
9 |
10 |
11 | const styles = StyleSheet.create({
12 | blue: {
13 | backgroundColor: 'blue',
14 | color: 'white',
15 | padding: 20,
16 | },
17 | red: {
18 | backgroundColor: 'red',
19 | },
20 | code: {
21 | backgroundColor: 'white',
22 | color: 'black',
23 | padding: 10,
24 | fontStyle: 'italic',
25 | fontWeight: 'bold',
26 | borderRadius: 4,
27 | },
28 | });
29 |
30 | const WithRenderStylesDiv = withRenderStyles(({ renderStyles: r, red }) => (
31 |
32 | I render my style using the widthRenderStyles HOC
33 |
34 | ));
35 |
36 | const InjectNativeDiv = ({ red }) => (
37 |
38 | I render my style using the styles property and
39 | {' '}
40 | injectNativeComponent
41 |
42 | );
43 |
44 | export default class App extends React.Component {
45 |
46 | constructor(props, context) {
47 | super(props, context);
48 | this.state = { timer: false };
49 | }
50 |
51 | componentDidMount() {
52 | setInterval(() => this.setState({ timer: !this.state.timer }), 500);
53 | }
54 |
55 | render() {
56 | const { timer } = this.state;
57 | return (
58 |
59 |
60 |
61 |
62 | );
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/examples/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { createStylesRenderer } from 'vstyle';
4 | import { StylesRendererProvider, injectNativeComponent } from 'react-vstyle';
5 | import App from './App';
6 |
7 | injectNativeComponent();
8 |
9 | const stylesRenderer = createStylesRenderer(window.STYLES_RENDERER_STATES);
10 | stylesRenderer.attach(document.getElementById('style'));
11 |
12 | ReactDOM.render(
13 |
14 |
15 | ,
16 | document.getElementById('content')
17 | );
18 |
--------------------------------------------------------------------------------
/lib/StylesRendererProvider.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var stylesRendererShape = require('./stylesRendererShape');
3 |
4 | var StylesRendererProvider = React.createClass({
5 |
6 | propTypes: {
7 | stylesRenderer: stylesRendererShape.isRequired,
8 | children: React.PropTypes.element.isRequired
9 | },
10 |
11 | childContextTypes: {
12 | _stylesRenderer: stylesRendererShape.isRequired
13 | },
14 |
15 | getChildContext: function () {
16 | return { _stylesRenderer: this.props.stylesRenderer };
17 | },
18 |
19 | componentWillReceiveProps: function (props) {
20 | if (props.stylesRenderer !== this.props.stylesRenderer) {
21 | throw new Error(
22 | ' does not support changing `stylesRenderer` on the fly.'
23 | );
24 | }
25 | },
26 |
27 | render: function () {
28 | return React.Children.only(this.props.children);
29 | }
30 | });
31 |
32 | module.exports = StylesRendererProvider;
33 |
--------------------------------------------------------------------------------
/lib/VStyleDOMComponent.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 François de Campredon
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | 'use strict';
18 |
19 | var React = require('react');
20 | var ReactDOMComponent = require('react/lib/ReactDOMComponent');
21 | var assign = require('object-assign');
22 |
23 | function VStyleDOMComponent() {
24 | ReactDOMComponent.apply(this, arguments);
25 | }
26 |
27 | VStyleDOMComponent.Mixin = {
28 |
29 | mountComponent: function (transaction, nativeParent, nativeContainerInfo, context) {
30 | this._currentElement = this._renderStyles(this._currentElement, context);
31 | return ReactDOMComponent.Mixin.mountComponent.call(
32 | this, transaction, nativeParent, nativeContainerInfo, context);
33 | },
34 |
35 | receiveComponent: function (nextElement, transaction, context) {
36 | nextElement = this._renderStyles(nextElement, context);
37 | return ReactDOMComponent.Mixin.receiveComponent.call(this, nextElement, transaction, context);
38 | },
39 |
40 | _renderStyles: function (element, context) {
41 | var elementStyles = element.props && element.props.styles;
42 | if (elementStyles) {
43 | var className =
44 | (element.className ? (' ' + element.className) : '') +
45 | context._stylesRenderer.renderStyles(elementStyles);
46 |
47 | return React.cloneElement(element, {
48 | className: className,
49 | styles: undefined
50 | });
51 | }
52 | return element;
53 | }
54 | };
55 |
56 | assign(
57 | VStyleDOMComponent.prototype,
58 | ReactDOMComponent.prototype,
59 | VStyleDOMComponent.Mixin
60 | );
61 |
62 | module.exports = VStyleDOMComponent;
63 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | var ReactInjection = require('react/lib/ReactInjection');
2 | var StylesRendererProvider = require('./StylesRendererProvider');
3 | var stylesRendererShape = require('./stylesRendererShape');
4 | var VStyleDOMComponent = require('./VStyleDOMComponent');
5 | var withRenderStyles = require('./withRenderStyles');
6 |
7 | exports.StylesRendererProvider = StylesRendererProvider;
8 | exports.stylesRendererShape = stylesRendererShape;
9 | exports.withRenderStyles = withRenderStyles;
10 | exports.injectNativeComponent = function () {
11 | ReactInjection.NativeComponent.injectGenericComponentClass(VStyleDOMComponent);
12 | };
13 |
--------------------------------------------------------------------------------
/lib/stylesRendererShape.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 | module.exports = React.PropTypes.shape({
4 | renderStyles: React.PropTypes.func.isRequired
5 | });
6 |
--------------------------------------------------------------------------------
/lib/withRenderStyles.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var assign = require('object-assign');
3 | var stylesRendererShape = require('./stylesRendererShape');
4 |
5 | function getDisplayName(WrappedComponent) {
6 | return WrappedComponent.displayName || WrappedComponent.name || 'Component';
7 | }
8 |
9 | function withRenderStyles(WrappedComponent) {
10 | var WithRenderStyles = React.createClass({
11 |
12 | contextTypes: {
13 | _stylesRenderer: stylesRendererShape.isRequired
14 | },
15 |
16 | render: function () {
17 | return React.createElement(
18 | WrappedComponent,
19 | assign(
20 | {},
21 | this.props,
22 | { renderStyles: this.context._stylesRenderer.renderStyles }
23 | )
24 | );
25 | }
26 | });
27 |
28 | WithRenderStyles.displayName = 'withRenderStyles(' + getDisplayName(WrappedComponent) + ')';
29 | WithRenderStyles.WrappedComponent = WrappedComponent;
30 |
31 | return WithRenderStyles;
32 | }
33 |
34 | module.exports = withRenderStyles;
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-vstyle",
3 | "version": "0.1.0",
4 | "description": "React bindings for vstyle",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "lint": "eslint lib"
8 | },
9 | "keywords": [
10 | "react",
11 | "vstyle",
12 | "css",
13 | "style",
14 | "cssinjs"
15 | ],
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/fdecampredon/react-vstyle.git"
19 | },
20 | "author": "François de Campredon (https://github.com/fdecampredon)",
21 | "bugs": {
22 | "url": "https://github.com/fdecampredon/react-vstyle/issues"
23 | },
24 | "license": "Apache-2.0",
25 | "peerDependencies": {
26 | "react": "^15.1.0"
27 | },
28 | "dependencies": {
29 | "object-assign": "^4.1.0"
30 | },
31 | "devDependencies": {
32 | "eslint": "^2.11.1",
33 | "eslint-config-airbnb": "^9.0.1",
34 | "eslint-plugin-import": "^1.8.1",
35 | "eslint-plugin-jsx-a11y": "^1.2.2",
36 | "eslint-plugin-react": "^5.1.1"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------