Skip to content

Instantly share code, notes, and snippets.

@fdecampredon
Created June 13, 2016 16:15
Show Gist options
  • Select an option

  • Save fdecampredon/94e873843cc13fcdb08077f0273f2f17 to your computer and use it in GitHub Desktop.

Select an option

Save fdecampredon/94e873843cc13fcdb08077f0273f2f17 to your computer and use it in GitHub Desktop.

Revisions

  1. fdecampredon created this gist Jun 13, 2016.
    120 changes: 120 additions & 0 deletions vstyle-component.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,120 @@

    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')
    );