Skip to content

Instantly share code, notes, and snippets.

@fdecampredon
Created June 13, 2016 16:15
Show Gist options
  • Save fdecampredon/94e873843cc13fcdb08077f0273f2f17 to your computer and use it in GitHub Desktop.
Save fdecampredon/94e873843cc13fcdb08077f0273f2f17 to your computer and use it in GitHub Desktop.
Vstyle Component
import React from 'react';
import ReactDOM from 'react-dom';
import { StyleSheet, createStylesRenderer } from 'vstyle';
import { StylesRendererProvider, withRenderStyles } from 'react-vstyle';
function createComponent({ component = 'div', ...styles }) {
const styleSheetDef = {
baseRule: {},
};
const stateProps = [];
Object.keys(styles).map(styleName => {
const value = styles[styleName];
if (
value &&
typeof value === 'object' &&
!Array.isArray(value) &&
/^[a-zA-Z]+$/.test(styleName)) {
stateProps.push(styleName);
styleSheetDef[styleName] = value;
} else {
styleSheetDef.baseRule[styleName] = value;
}
});
const styleSheet = StyleSheet.create(styleSheetDef);
return withRenderStyles(({ renderStyles, ...props }) =>
React.createElement(
component,
{
...props,
className: (`${props.className} ` || '') +
renderStyles(
styleSheet.baseRule,
stateProps.map(prop => props[prop] && styleSheet[prop])
),
}
)
);
}
const stylesRenderer = createStylesRenderer(window.STYLES_RENDERER_STATES);
stylesRenderer.attach(document.getElementById('style'));
const Header = createComponent({
component: 'header',
display: 'flex',
alignItems: 'center',
});
const AddTodoButton = createComponent({
component: 'button',
background: 'grey',
valid: {
background: 'green',
},
});
const TodoRow = createComponent({
color: '#333',
done: {
color: 'grey',
textDecoration: 'line-through',
},
});
class App extends React.Component {
state = { todos: [], text: '' };
onTextChange = (e) => {
this.setState({ text: e.target.value });
}
onTodoDone = (index) => {
const { todos } = this.state;
this.setState({
todos: todos
.map((todo, i) => (
i === index ?
{ ...todo, done: true } :
todo
)),
});
}
addTodo = () => {
const { todos, text } = this.state;
this.setState({ todos: todos.concat({ done: false, text }), text: '' });
}
render() {
const { todos, text } = this.state;
const canSave = !!text.trim();
return (
<div>
<Header>
<input type="text" value={text} onChange={this.onTextChange} />
<AddTodoButton valid={canSave} onClick={canSave && this.addTodo}>
Add Todo
</AddTodoButton>
</Header>
<div>
{
todos.map(({ text, done }, index) =>
<TodoRow done={done} onClick={() => this.onTodoDone(index)}>{text}</TodoRow>
)
}
</div>
</div>
);
}
}
ReactDOM.render(
<StylesRendererProvider stylesRenderer={stylesRenderer}>
<App />
</StylesRendererProvider>,
document.getElementById('content')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment