Skip to content

Instantly share code, notes, and snippets.

@dlmanning
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dlmanning/262c8df1c8e70e980d04 to your computer and use it in GitHub Desktop.
Save dlmanning/262c8df1c8e70e980d04 to your computer and use it in GitHub Desktop.
react-svg-flexbox
import React from 'react';
import { FlexContext, FlexBox } from 'flex';
const { Component } = React;
class Container extends Component {
render () {
console.log('Rendering Container');
return (
<g>
<rect fill={this.props.color}
x="0"
y="0"
width={this.props.layout.width}
height={this.props.layout.height} />
{this.props.children}
</g>
);
}
}
const Backdrop = FlexBox(Container, {
flexDirection: 'row',
flex: 1,
padding: 40,
justifyContent: 'flex-start'
});
const Square = FlexBox(Container, {
height: 40,
width: 40
});
const containerStyle = {
width: 400,
height: 400
}
export default class App extends Component {
render () {
return (
<svg height="600" width="600">
<FlexContext layout={containerStyle}>
<Backdrop color="#CE6E09">
<Square color="#470300" />
<Square color="#F6B968" />
<Square color="#470300" />
</Backdrop>
</FlexContext>
</svg>
)
}
}
import React from 'react';
import { FlexContext, FlexBox } from 'flex';
const { Component } = React;
class Container extends Component {
render () {
console.log('Rendering Container');
return (
<g>
<rect fill={this.props.color}
x="0"
y="0"
width={this.props.layout.width}
height={this.props.layout.height} />
{this.props.children}
</g>
);
}
}
const Backdrop = FlexBox(Container, {
flexDirection: 'row',
flex: 1,
padding: 40,
justifyContent: 'flex-start'
});
const Square = FlexBox(Container, {
height: 40,
width: 40
});
const containerStyle = {
width: 400,
height: 400
}
export default class App extends Component {
render () {
const board = [];
for (let i = 0; i < 64; i++) {
board[i] = i;
}
return (
<svg height="600" width="600">
<FlexContext layout={containerStyle}>
<Backdrop color="#CE6E09">
{board.map(id => <Square key={id} color={id % 2 ? '#470300' : '#F6B968'} />)}
</Backdrop>
</FlexContext>
</svg>
)
}
}
import React from 'react';
import computeLayout from 'css-layout';
const { Component } = React;
const styles = { children: [] };
function setLayout (style, layout = styles, path = []) {
if (layout.style === undefined) {
layout.style = style;
} else {
let childLayout = { style: style, children: [] };
layout.children.push(childLayout);
path.push(layout.children.length - 1);
layout = childLayout;
}
return {
path: path.slice(),
setLayout : function (style) {
return setLayout(style, layout, path.slice());
}
}
}
export class FlexContext extends Component {
static childContextTypes = {
setLayout: React.PropTypes.func.isRequired,
getLayout: React.PropTypes.func.isRequired
}
constructor (props, context) {
super();
this.state = {};
const layout = props.layout || {}
const { setLayout: layoutFunc } = setLayout(layout);
this.setLayout = layoutFunc;
}
getLayout = (path = []) => {
if (this.state.flexStyles !== undefined && path.length > 0) {
let layout = this.state.flexStyles;
path.forEach(childIndex => {
layout = layout.children[childIndex]
});
return layout;
} else {
return {
top: 0,
left: 0,
width: 0,
height: 0
};
}
}
getChildContext () {
return {
setLayout: this.setLayout,
getLayout: this.getLayout
}
}
render () {
console.log('Rendering FlexContainer');
return <g>{this.props.children}</g>;
}
componentDidMount () {
console.log('FlexContainer did mount');
const flexStyles = computeLayout(styles);
this.setState({ flexStyles: flexStyles });
}
}
export const FlexBox = (Composed, style = {}) => class extends Component {
static displayName = 'FlexBox';
static contextTypes = {
setLayout: React.PropTypes.func.isRequired,
getLayout: React.PropTypes.func.isRequired
}
static childContextTypes = {
setLayout: React.PropTypes.func.isRequired
}
constructor (props, context) {
super();
const { setLayout: layoutFunc, path} = context.setLayout(style);
this.setLayout = layoutFunc;
this.pathToNode = path;
}
getChildContext () {
return {
setLayout: this.setLayout
}
}
render () {
const layout = this.context.getLayout(this.pathToNode);
const transformation = `translate(${layout.left},${layout.top})`
return <g transform={transformation}><Composed {...this.props} layout={layout}/></g>;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment