├── .babelrc
├── .gitignore
├── README.md
├── index.js
├── lib
├── flex.js
└── flexbox-props.js
├── package.json
├── src
├── flex.jsx
└── flexbox-props.js
├── test
├── chessboard.jsx
├── index.html
├── main.js
├── ref.html
└── test.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "optional": [
3 | "es7.decorators",
4 | "es7.classProperties",
5 | "es7.objectRestSpread",
6 | "runtime"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This makes use of parent context, currently only found on react >= 0.14 in [react master](https://github.com/facebook/react).
2 |
3 | To install from react master branch:
4 | ```
5 | git clone https://github.com/facebook/react.git
6 | cd react
7 | npm run build
8 | cd npm-react
9 | npm link
10 | ```
11 |
12 | Then in your project folder:
13 | ```
14 | npm link react
15 | ```
16 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/flex.js');
2 |
--------------------------------------------------------------------------------
/lib/flex.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _inherits = require('babel-runtime/helpers/inherits')['default'];
4 |
5 | var _get = require('babel-runtime/helpers/get')['default'];
6 |
7 | var _createClass = require('babel-runtime/helpers/create-class')['default'];
8 |
9 | var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];
10 |
11 | var _extends = require('babel-runtime/helpers/extends')['default'];
12 |
13 | var _Object$assign = require('babel-runtime/core-js/object/assign')['default'];
14 |
15 | var _Object$keys = require('babel-runtime/core-js/object/keys')['default'];
16 |
17 | var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
18 |
19 | Object.defineProperty(exports, '__esModule', {
20 | value: true
21 | });
22 |
23 | var _react = require('react');
24 |
25 | var _react2 = _interopRequireDefault(_react);
26 |
27 | var _wolfy87Eventemitter = require('wolfy87-eventemitter');
28 |
29 | var _wolfy87Eventemitter2 = _interopRequireDefault(_wolfy87Eventemitter);
30 |
31 | var _cssLayout = require('css-layout');
32 |
33 | var _cssLayout2 = _interopRequireDefault(_cssLayout);
34 |
35 | var _flexboxProps = require('./flexbox-props');
36 |
37 | var _flexboxProps2 = _interopRequireDefault(_flexboxProps);
38 |
39 | var Component = _react2['default'].Component;
40 |
41 | function _setStyle(style, styles) {
42 | if (style === undefined) style = {};
43 | var path = arguments[2] === undefined ? [] : arguments[2];
44 |
45 | if (styles.style === undefined) {
46 | styles.style = style;
47 | } else {
48 | var childStyle = { style: style, children: [] };
49 | styles.children.push(childStyle);
50 | path.push(styles.children.length - 1);
51 |
52 | styles = childStyle;
53 | }
54 |
55 | return {
56 | path: path.slice(),
57 | setStyle: function setStyle(childStyle) {
58 | return _setStyle(childStyle, styles, path.slice());
59 | }
60 | };
61 | }
62 |
63 | var FlexContext = (function (_Component) {
64 | function FlexContext(props, context) {
65 | var _this = this;
66 |
67 | _classCallCheck(this, FlexContext);
68 |
69 | _get(Object.getPrototypeOf(FlexContext.prototype), 'constructor', this).call(this, props);
70 |
71 | this.deregister = function (cb) {
72 | _this.layoutNotifier.removeListener('layout-update', cb);
73 | };
74 |
75 | this.waitForLayoutCalculation = function (cb) {
76 | _this.layoutNotifier.once('layout-update', cb);
77 | };
78 |
79 | this.layoutNotifier = new _wolfy87Eventemitter2['default']();
80 |
81 | this.stylesRoot = { children: [] };
82 | this.styleTools = {};
83 | }
84 |
85 | _inherits(FlexContext, _Component);
86 |
87 | _createClass(FlexContext, [{
88 | key: 'getChildContext',
89 | value: function getChildContext() {
90 | return {
91 | styleTools: this.styleTools,
92 | waitForLayoutCalculation: this.waitForLayoutCalculation,
93 | deregister: this.deregister
94 | };
95 | }
96 | }, {
97 | key: 'render',
98 | value: function render() {
99 | return _react2['default'].createElement(
100 | 'g',
101 | null,
102 | this.props.children
103 | );
104 | }
105 | }, {
106 | key: 'startNewStyleTree',
107 | value: function startNewStyleTree() {
108 | this.stylesRoot = { children: [] };
109 |
110 | var _setStyle2 = _setStyle(undefined, this.stylesRoot);
111 |
112 | var layoutFunc = _setStyle2.setStyle;
113 |
114 | this.styleTools.setStyle = layoutFunc;
115 | }
116 | }, {
117 | key: 'computeLayoutAndBroadcastResults',
118 | value: function computeLayoutAndBroadcastResults() {
119 | var flexLayout = (0, _cssLayout2['default'])(this.stylesRoot);
120 | this.layoutNotifier.emit('layout-update', flexLayout);
121 | }
122 | }, {
123 | key: 'componentWillMount',
124 | value: function componentWillMount() {
125 | this.startNewStyleTree();
126 | }
127 | }, {
128 | key: 'componentDidMount',
129 | value: function componentDidMount() {
130 | this.computeLayoutAndBroadcastResults();
131 | }
132 | }, {
133 | key: 'componentWillUpdate',
134 | value: function componentWillUpdate() {
135 | this.startNewStyleTree();
136 | }
137 | }, {
138 | key: 'componentDidUpdate',
139 | value: function componentDidUpdate() {
140 | this.computeLayoutAndBroadcastResults();
141 | }
142 | }], [{
143 | key: 'childContextTypes',
144 | value: {
145 | styleTools: _react2['default'].PropTypes.object.isRequired,
146 | waitForLayoutCalculation: _react2['default'].PropTypes.func.isRequired,
147 | deregister: _react2['default'].PropTypes.func.isRequired
148 | },
149 | enumerable: true
150 | }]);
151 |
152 | return FlexContext;
153 | })(Component);
154 |
155 | exports.FlexContext = FlexContext;
156 | var FlexBox = function FlexBox(Composed) {
157 | var componentStyles = arguments[1] === undefined ? {} : arguments[1];
158 | return (function (_Component2) {
159 | var _class = function _class(props, context) {
160 | var _this2 = this;
161 |
162 | _classCallCheck(this, _class);
163 |
164 | _get(Object.getPrototypeOf(_class.prototype), 'constructor', this).call(this, props);
165 |
166 | this.handleLayoutCalculation = function (layout) {
167 | _this2.setState({ layout: _this2.getMyLayout(layout) });
168 | };
169 |
170 | var style = _Object$assign(componentStyles, props.style);
171 |
172 | var _partitionStyles = partitionStyles(style);
173 |
174 | var svgStyles = _partitionStyles.svgStyles;
175 | var flexStyles = _partitionStyles.flexStyles;
176 |
177 | this.flexStyles = flexStyles;
178 | this.styleTools = {};
179 |
180 | this.state = {
181 | layout: { top: 0, left: 0, width: 0, height: 0 },
182 | styles: svgStyles
183 | };
184 | };
185 |
186 | _inherits(_class, _Component2);
187 |
188 | _createClass(_class, [{
189 | key: 'getMyLayout',
190 | value: function getMyLayout(layout) {
191 | this.pathToNode.forEach(function (childIndex) {
192 | layout = layout.children[childIndex];
193 | });
194 |
195 | return layout;
196 | }
197 | }, {
198 | key: 'componentWillMount',
199 | value: function componentWillMount() {
200 | var _context$styleTools$setStyle = this.context.styleTools.setStyle(this.flexStyles);
201 |
202 | var setStyleFunc = _context$styleTools$setStyle.setStyle;
203 | var path = _context$styleTools$setStyle.path;
204 |
205 | this.styleTools.setStyle = setStyleFunc;
206 | this.pathToNode = path;
207 |
208 | this.context.waitForLayoutCalculation(this.handleLayoutCalculation);
209 | }
210 | }, {
211 | key: 'componentWillUnmount',
212 | value: function componentWillUnmount() {
213 | this.context.deregister(this.handleLayoutCalculation);
214 | }
215 | }, {
216 | key: 'componentWillReceiveProps',
217 | value: function componentWillReceiveProps() {
218 | var _context$styleTools$setStyle2 = this.context.styleTools.setStyle(this.flexStyles);
219 |
220 | var setStyleFunc = _context$styleTools$setStyle2.setStyle;
221 | var path = _context$styleTools$setStyle2.path;
222 |
223 | this.styleTools.setStyle = setStyleFunc;
224 | this.pathToNode = path;
225 |
226 | this.context.waitForLayoutCalculation(this.handleLayoutCalculation);
227 | }
228 | }, {
229 | key: 'getChildContext',
230 | value: function getChildContext() {
231 | return {
232 | styleTools: this.styleTools
233 | };
234 | }
235 | }, {
236 | key: 'render',
237 | value: function render() {
238 | var transformation = 'translate(' + this.state.layout.left + ',' + this.state.layout.top + ')';
239 | return _react2['default'].createElement(
240 | 'g',
241 | { transform: transformation },
242 | _react2['default'].createElement(Composed, _extends({ layout: this.state.layout, style: this.state.styles }, this.props))
243 | );
244 | }
245 | }], [{
246 | key: 'displayName',
247 | value: 'FlexBox',
248 | enumerable: true
249 | }, {
250 | key: 'contextTypes',
251 | value: {
252 | styleTools: _react2['default'].PropTypes.object.isRequired,
253 | waitForLayoutCalculation: _react2['default'].PropTypes.func.isRequired,
254 | deregister: _react2['default'].PropTypes.func.isRequired
255 | },
256 | enumerable: true
257 | }, {
258 | key: 'childContextTypes',
259 | value: {
260 | styleTools: _react2['default'].PropTypes.object.isRequired
261 | },
262 | enumerable: true
263 | }]);
264 |
265 | return _class;
266 | })(Component);
267 | };
268 |
269 | exports.FlexBox = FlexBox;
270 | function partitionStyles(styles) {
271 | return _Object$keys(styles).reduce(function (partitions, property) {
272 | if ((0, _flexboxProps2['default'])(property)) {
273 | partitions.flexStyles[property] = styles[property];
274 | } else {
275 | partitions.svgStyles[property] = styles[property];
276 | }
277 |
278 | return partitions;
279 | }, { svgStyles: {}, flexStyles: {} });
280 | }
--------------------------------------------------------------------------------
/lib/flexbox-props.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _Set = require('babel-runtime/core-js/set')['default'];
4 |
5 | Object.defineProperty(exports, '__esModule', {
6 | value: true
7 | });
8 | exports['default'] = isFlexBoxProperty;
9 | var flexboxProperties = new _Set(['flexDirection', 'justifyContent', 'alignItems', 'alignSelf', 'position', 'flexWrap', 'flex', 'width', 'height', 'maxWidth', 'maxHeight', 'minWidth', 'minHeight', 'margin', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom', 'padding', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom', 'borderWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth', 'borderBottomWidth', 'left', 'top', 'right', 'bottom']);
10 |
11 | function isFlexBoxProperty(propertyName) {
12 | return flexboxProperties.has(propertyName);
13 | }
14 |
15 | module.exports = exports['default'];
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-flexbox-svg",
3 | "version": "0.9.3",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test-serve": "webpack-dev-server --content-base test/ --hot --inline -d",
8 | "prepublish": "babel src --out-dir lib"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "peerDependencies": {
13 | "react": "0.14.0-alpha3"
14 | },
15 | "dependencies": {
16 | "babel-runtime": "^5.1.11",
17 | "css-layout": "^1.0.0",
18 | "webpack": "^1.12.1",
19 | "webpack-dev-server": "^1.10.1",
20 | "wolfy87-eventemitter": "^4.2.11"
21 | },
22 | "devDependencies": {
23 | "babel": "^5.1.11",
24 | "babel-core": "^5.1.10",
25 | "babel-loader": "^5.0.0",
26 | "webpack": "^1.8.5",
27 | "webpack-dev-server": "^1.8.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/flex.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import EventEmitter from 'wolfy87-eventemitter';
3 | import computeLayout from 'css-layout';
4 | import isFlexBoxProperty from './flexbox-props';
5 | const { Component } = React;
6 |
7 | function setStyle (style = {}, styles, path = []) {
8 | if (styles.style === undefined) {
9 | styles.style = style;
10 | } else {
11 | let childStyle = { style: style, children: [] };
12 | styles.children.push(childStyle);
13 | path.push(styles.children.length - 1);
14 |
15 | styles = childStyle;
16 | }
17 |
18 | return {
19 | path: path.slice(),
20 | setStyle : function (childStyle) {
21 | return setStyle(childStyle, styles, path.slice());
22 | }
23 | }
24 | }
25 |
26 | export class FlexContext extends Component {
27 | static childContextTypes = {
28 | styleTools: React.PropTypes.object.isRequired,
29 | waitForLayoutCalculation: React.PropTypes.func.isRequired,
30 | deregister: React.PropTypes.func.isRequired
31 | }
32 |
33 | constructor (props, context) {
34 | super(props);
35 |
36 | this.layoutNotifier = new EventEmitter();
37 |
38 | this.stylesRoot = { children: [] };
39 | this.styleTools = {};
40 | }
41 |
42 | deregister = cb => {
43 | this.layoutNotifier.removeListener('layout-update', cb)
44 | }
45 |
46 | waitForLayoutCalculation = (cb) => {
47 | this.layoutNotifier.once('layout-update', cb);
48 | }
49 |
50 | getChildContext () {
51 | return {
52 | styleTools: this.styleTools,
53 | waitForLayoutCalculation: this.waitForLayoutCalculation,
54 | deregister: this.deregister
55 | }
56 | }
57 |
58 | render () {
59 | return