Skip to content

Instantly share code, notes, and snippets.

@oroce
Created April 25, 2017 13:28
Show Gist options
  • Save oroce/d4716a1251a01f68e6db3f5b2faa5837 to your computer and use it in GitHub Desktop.
Save oroce/d4716a1251a01f68e6db3f5b2faa5837 to your computer and use it in GitHub Desktop.

Revisions

  1. oroce created this gist Apr 25, 2017.
    1 change: 1 addition & 0 deletions esnextbin.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    made with [esnextbin](http://esnextb.in)
    22 changes: 22 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>ESNextbin Sketch</title>
    <!-- put additional styles and scripts here -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <style>
    .key-value-row-remove {
    display: none;
    }
    .key-value-row-key-item input {
    background:rgba(0,0,0,0);
    border:none;
    }
    </style>
    </head>
    <body>
    <!-- put markup and other contents here -->
    <div id="container"></div>
    </body>
    </html>
    304 changes: 304 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,304 @@
    import React, { PropTypes } from 'react';
    import { Grid, Col, Row, DropdownButton, MenuItem } from 'react-bootstrap';
    import ReactDOM from 'react-dom';
    import tmpl from 'lodash.template';
    import set from 'lodash.set';
    import get from 'lodash.get';
    const c = 'key-value';

    const KeyValue = React.createClass({
    displayName: 'KeyValue',
    propTypes: {
    rows: PropTypes.arrayOf(PropTypes.shape({
    keyItem: PropTypes.string,
    valueItem: PropTypes.string
    })),
    onChange: PropTypes.func,
    customAddButtonRenderer: PropTypes.func,
    keyInputPlaceholder: PropTypes.string,
    valueInputPlaceholder: PropTypes.string,
    hideLabels: PropTypes.bool
    },
    getDefaultProps() {
    return {
    rows: [],
    onChange: () => {},
    keyInputPlaceholder: '',
    valueInputPlaceholder: '',
    hideLabels: false
    };
    },
    getInitialState() {
    return {
    rows: [
    ...this.props.rows
    ]
    };
    },
    handleAddNew() {
    this.setState({
    rows: [
    ...this.state.rows,
    {
    keyItem: '',
    valueItem: ''
    }
    ]
    }, () => {
    this.props.onChange([...this.state.rows]);
    });
    },
    handleKeyItemChange(index, value) {
    this.setState({
    rows: this.state.rows.map((row, i) => {
    if (index !== i) {
    return row;
    }
    return {
    ...row,
    keyItem: value
    };
    })
    }, () => {
    this.props.onChange([...this.state.rows]);
    });
    },
    handleValueItemChange(index, value) {
    this.setState({
    rows: this.state.rows.map((row, i) => {
    if (index !== i) {
    return row;
    }
    return {
    ...row,
    valueItem: value
    };
    })
    }, () => {
    this.props.onChange([...this.state.rows]);
    });
    },
    handleRemove(index) {
    this.setState({
    rows: this.state.rows.filter((row, i) => i !== index)
    }, () => {
    this.props.onChange([...this.state.rows]);
    });
    },
    renderLabelText(text) {
    if (this.props.hideLabels === true) {
    return null;
    }
    return (
    <span>
    { text }
    </span>
    );
    },
    renderKeyItem(index, value) {
    return (
    <label>
    { this.renderLabelText('Key:') }
    <input
    type="text"
    value={ value }
    placeholder={ this.props.keyInputPlaceholder }
    onChange={ (e) => this.handleKeyItemChange(index, e.currentTarget.value) }
    />
    </label>
    );
    },
    renderValueItem(index, value) {
    return (
    <label>
    { this.renderLabelText('Value:') }
    <input
    type="text"
    value={ value }
    placeholder={ this.props.valueInputPlaceholder }
    onChange={ (e) => this.handleValueItemChange(index, e.currentTarget.value) }
    />
    </label>
    );
    },
    renderRows() {
    return this.state.rows.map((row, i) => (
    <div
    key={ `key-value-row-${i}` }
    className={ `${c}-row` }
    >
    <div className={ `${c}-row-key-item` }>
    { this.renderKeyItem(i, row.keyItem) }
    </div>
    <div className={ `${c}-row-value-item` }>
    { this.renderValueItem(i, row.valueItem) }
    </div>
    <div className={ `${c}-row-remove` }>
    <button
    onClick={ () => this.handleRemove(i) }
    >
    -
    </button>
    </div>
    </div>
    ));
    },
    renderAddButton() {
    if (typeof this.props.customAddButtonRenderer === 'function') {
    return this.props.customAddButtonRenderer(this.handleAddNew);
    }
    return (
    <button
    onClick={ this.handleAddNew }
    >
    Add new
    </button>
    );
    },
    render() {
    return (
    <div className={ c }>
    <div className={ `${c}-rows` }>
    { this.renderRows() }
    </div>
    <div className={ `${c}-add-new` }>
    { this.renderAddButton() }
    </div>
    </div>
    );
    }
    });

    const slides = [{
    src: `<div class="slide slideContainer" style="position: relative"><div class="componentContainer " style="position: absolute;line-height: normal;top: 0px; left: 0px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#df6363" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 0px; left: 202px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#dfcf63" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 0px; left: 404px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#86e3c9" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 188px; left: 0px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#5061b4" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 188px; left: 202px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#9c5abe" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 188px; left: 404px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#463e40" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 20px; left: 60px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><b><font color="#ffffff"><a href="{{firstbox.link}}">{{firstbox.label}}</a></font></b><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 20px; left: 250px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><b><font color="#ffffff"><a href="{{secondbox.link}}">{{secondbox.label}}</a><br></font></b><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 20px; left: 480px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><b><font color="#ffffff"><a href="{{thirdbox.link}}">{{thirdbox.label}}</a></b><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 220px; left: 60px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><font color="#ffffff"><b><a href="{{fourthbox.link}}">{{fourthbox.label}}</a></b></font><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 220px; left: 250px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><font color="#ffffff"><b><a href="{{fifthbox.link}}">{{fifthbox.label}}</a></b></font><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 250px; left: 480px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><font color="#ffffff"><b><a href="{{sixthbox.link}}">{{sixthbox.label}}</a></b></font><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 130px; left: 20px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{firstbox.description}}<br></font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 130px; left: 229px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{secondbox.description}}<br></font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 130px; left: 435px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{thirdbox.description}}<br></font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 325px; left: 20px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{fourthbox.description}}</font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 325px; left: 230px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{fifthbox.description}}</font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;position: absolute;line-height: normal;top: 325px; left: 430px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{sixthbox.description}}</font><br></div></div></div></div>`,
    type: 'toc'
    }, {
    src: '',
    type: 'introduction'
    }, {
    src: '',
    type: 'social overview'
    }, {
    src: '',
    type: 'technical seo'
    }];
    class App extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
    slides: [{
    id: 'f38c',
    type: 'toc',
    active: true,
    options: {},
    }]
    };
    }
    getVariables(src) {
    return src.match(/{{([\s\S]+?)}}/g).map(k => k.replace(/[^.a-z0-9_\-]/gi, ''));
    }
    getSlideSrc(type) {
    return slides.find(s => s.type === type).src;
    }
    getActiveSlide() {
    return this.state.slides.find(slide => slide.active);
    }
    handleOnChange(id, data) {
    const options = data.reduce((grp, item) => {
    set(grp, item.keyItem, item.valueItem);
    return grp;
    }, {});
    this.setState({
    slides: this.state.slides.map(slide => {
    if (slide.id === id) {
    return Object.assign({}, slide, {
    options: options
    });
    }
    return slide
    })
    });
    }
    handleSetActive(slide) {
    this.setState({
    slides: slides.map(s => {
    return Object.assign({}, slide, {
    active: slide.id === s.id
    });
    })
    });
    }
    renderEditor() {
    const active = this.getActiveSlide();
    const src = this.getSlideSrc(active.type);
    const rows = this.getVariables(src).map(k => ({keyItem: k}));
    const addButton = (handleAddNew) => {
    return null;
    };
    return (
    <div>
    <label>Type: <b>{ active.type }</b></label>
    <KeyValue
    rows={ rows }
    customAddButtonRenderer={ addButton }
    onChange={ (d) => this.handleOnChange(active.id, d) } />
    </div>
    );

    }
    renderSlides() {
    return this.state.slides.map(slide => this.renderSlide(slide));
    }
    renderSlide(slide) {
    const src = this.getSlideSrc(slide.type);
    const variables = this.getVariables(src);
    let options = Object.assign({}, slide.options || {});

    variables.forEach(variable => {
    if (!get(options, variable)) {
    set(options, variable, variable);
    }
    });
    const content = this.renderSlideContent(src, options);
    const borderColor = slide.active ? 'red' : 'black';
    return (
    <Row key={ slide.id } onClick={ this.handleSetActive.bind(this, slide) }>
    <Grid md={12} style={ {height: '400px', width: '640px', border: `solid 1px ${borderColor}`} }>
    <div dangerouslySetInnerHTML={ {__html: content} } />
    </Grid>
    </Row>
    );
    }
    renderSlideContent(text, options) {
    console.log('render', options);
    return tmpl(text, {interpolate: /{{([\s\S]+?)}}/g})(options);
    }
    render() {
    const types = slides.map(slide => slide.type);
    const items = types.map(type => {
    return (<MenuItem eventKey={ type }>{ type }</MenuItem>);
    });
    return (
    <Grid>
    <Row>
    <Col md={3} className="editors">
    { this.renderEditor() }
    </Col>
    <Col md={9} className="previews">
    { this.renderSlides() }
    </Col>
    </Row>
    <Row>
    <Col>
    <DropdownButton title="Add new" title="Add new" key="addnew" id="addnew">
    { items }
    </DropdownButton>
    </Col>
    </Row>
    </Grid>
    );
    }
    };


    ReactDOM.render(<App />, document.getElementById('container'));
    13 changes: 13 additions & 0 deletions package.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    {
    "name": "esnextbin-sketch",
    "version": "0.0.0",
    "dependencies": {
    "react": "15.5.4",
    "react-bootstrap": "0.30.10",
    "react-dom": "15.5.4",
    "lodash.template": "4.4.0",
    "lodash.set": "4.3.2",
    "lodash.get": "4.4.2",
    "babel-runtime": "6.23.0"
    }
    }
    462 changes: 462 additions & 0 deletions transpiled.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,462 @@
    'use strict';

    var _defineProperty2 = require('babel-runtime/helpers/defineProperty');

    var _defineProperty3 = _interopRequireDefault(_defineProperty2);

    var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

    var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

    var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

    var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

    var _createClass2 = require('babel-runtime/helpers/createClass');

    var _createClass3 = _interopRequireDefault(_createClass2);

    var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

    var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

    var _inherits2 = require('babel-runtime/helpers/inherits');

    var _inherits3 = _interopRequireDefault(_inherits2);

    var _extends2 = require('babel-runtime/helpers/extends');

    var _extends3 = _interopRequireDefault(_extends2);

    var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');

    var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);

    var _react = require('react');

    var _react2 = _interopRequireDefault(_react);

    var _reactBootstrap = require('react-bootstrap');

    var _reactDom = require('react-dom');

    var _reactDom2 = _interopRequireDefault(_reactDom);

    var _lodash = require('lodash.template');

    var _lodash2 = _interopRequireDefault(_lodash);

    var _lodash3 = require('lodash.set');

    var _lodash4 = _interopRequireDefault(_lodash3);

    var _lodash5 = require('lodash.get');

    var _lodash6 = _interopRequireDefault(_lodash5);

    function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

    var c = 'key-value';

    var KeyValue = _react2.default.createClass({
    displayName: 'KeyValue',
    propTypes: {
    rows: _react.PropTypes.arrayOf(_react.PropTypes.shape({
    keyItem: _react.PropTypes.string,
    valueItem: _react.PropTypes.string
    })),
    onChange: _react.PropTypes.func,
    customAddButtonRenderer: _react.PropTypes.func,
    keyInputPlaceholder: _react.PropTypes.string,
    valueInputPlaceholder: _react.PropTypes.string,
    hideLabels: _react.PropTypes.bool
    },
    getDefaultProps: function getDefaultProps() {
    return {
    rows: [],
    onChange: function onChange() {},
    keyInputPlaceholder: '',
    valueInputPlaceholder: '',
    hideLabels: false
    };
    },
    getInitialState: function getInitialState() {
    return {
    rows: [].concat((0, _toConsumableArray3.default)(this.props.rows))
    };
    },
    handleAddNew: function handleAddNew() {
    var _this = this;

    this.setState({
    rows: [].concat((0, _toConsumableArray3.default)(this.state.rows), [{
    keyItem: '',
    valueItem: ''
    }])
    }, function () {
    _this.props.onChange([].concat((0, _toConsumableArray3.default)(_this.state.rows)));
    });
    },
    handleKeyItemChange: function handleKeyItemChange(index, value) {
    var _this2 = this;

    this.setState({
    rows: this.state.rows.map(function (row, i) {
    if (index !== i) {
    return row;
    }
    return (0, _extends3.default)({}, row, {
    keyItem: value
    });
    })
    }, function () {
    _this2.props.onChange([].concat((0, _toConsumableArray3.default)(_this2.state.rows)));
    });
    },
    handleValueItemChange: function handleValueItemChange(index, value) {
    var _this3 = this;

    this.setState({
    rows: this.state.rows.map(function (row, i) {
    if (index !== i) {
    return row;
    }
    return (0, _extends3.default)({}, row, {
    valueItem: value
    });
    })
    }, function () {
    _this3.props.onChange([].concat((0, _toConsumableArray3.default)(_this3.state.rows)));
    });
    },
    handleRemove: function handleRemove(index) {
    var _this4 = this;

    this.setState({
    rows: this.state.rows.filter(function (row, i) {
    return i !== index;
    })
    }, function () {
    _this4.props.onChange([].concat((0, _toConsumableArray3.default)(_this4.state.rows)));
    });
    },
    renderLabelText: function renderLabelText(text) {
    if (this.props.hideLabels === true) {
    return null;
    }
    return _react2.default.createElement(
    'span',
    null,
    text
    );
    },
    renderKeyItem: function renderKeyItem(index, value) {
    var _this5 = this;

    return _react2.default.createElement(
    'label',
    null,
    this.renderLabelText('Key:'),
    _react2.default.createElement('input', {
    type: 'text',
    value: value,
    placeholder: this.props.keyInputPlaceholder,
    onChange: function onChange(e) {
    return _this5.handleKeyItemChange(index, e.currentTarget.value);
    }
    })
    );
    },
    renderValueItem: function renderValueItem(index, value) {
    var _this6 = this;

    return _react2.default.createElement(
    'label',
    null,
    this.renderLabelText('Value:'),
    _react2.default.createElement('input', {
    type: 'text',
    value: value,
    placeholder: this.props.valueInputPlaceholder,
    onChange: function onChange(e) {
    return _this6.handleValueItemChange(index, e.currentTarget.value);
    }
    })
    );
    },
    renderRows: function renderRows() {
    var _this7 = this;

    return this.state.rows.map(function (row, i) {
    return _react2.default.createElement(
    'div',
    {
    key: 'key-value-row-' + i,
    className: c + '-row'
    },
    _react2.default.createElement(
    'div',
    { className: c + '-row-key-item' },
    _this7.renderKeyItem(i, row.keyItem)
    ),
    _react2.default.createElement(
    'div',
    { className: c + '-row-value-item' },
    _this7.renderValueItem(i, row.valueItem)
    ),
    _react2.default.createElement(
    'div',
    { className: c + '-row-remove' },
    _react2.default.createElement(
    'button',
    {
    onClick: function onClick() {
    return _this7.handleRemove(i);
    }
    },
    '-'
    )
    )
    );
    });
    },
    renderAddButton: function renderAddButton() {
    if (typeof this.props.customAddButtonRenderer === 'function') {
    return this.props.customAddButtonRenderer(this.handleAddNew);
    }
    return _react2.default.createElement(
    'button',
    {
    onClick: this.handleAddNew
    },
    'Add new'
    );
    },
    render: function render() {
    return _react2.default.createElement(
    'div',
    { className: c },
    _react2.default.createElement(
    'div',
    { className: c + '-rows' },
    this.renderRows()
    ),
    _react2.default.createElement(
    'div',
    { className: c + '-add-new' },
    this.renderAddButton()
    )
    );
    }
    });

    var slides = [{
    src: '<div class="slide slideContainer" style="position: relative"><div class="componentContainer " style="position: absolute;line-height: normal;top: 0px; left: 0px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#df6363" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 0px; left: 202px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#dfcf63" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 0px; left: 404px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#86e3c9" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 188px; left: 0px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#5061b4" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 188px; left: 202px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#9c5abe" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 188px; left: 404px; -webkit-transform: ; -moz-transform: ; transform: ; width: 202.31px; height: 189.05px;"><div class="transformContainer" style="-webkit-transform: scale(, );-moz-transform: scale(, );transform: scale(, )"><svg fill="#463e40" height="189.04984273522794" width="202.31125704531308" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 50 50" preserveAspectRatio="none"><rect width="50" height="50"></rect></svg></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 20px; left: 60px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><b><font color="#ffffff"><a href="{{firstbox.link}}">{{firstbox.label}}</a></font></b><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 20px; left: 250px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><b><font color="#ffffff"><a href="{{secondbox.link}}">{{secondbox.label}}</a><br></font></b><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 20px; left: 480px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><b><font color="#ffffff"><a href="{{thirdbox.link}}">{{thirdbox.label}}</a></b><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 220px; left: 60px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><font color="#ffffff"><b><a href="{{fourthbox.link}}">{{fourthbox.label}}</a></b></font><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 220px; left: 250px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><font color="#ffffff"><b><a href="{{fifthbox.link}}">{{fifthbox.label}}</a></b></font><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 250px; left: 480px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 72px;" class="antialias"><font><font color="#ffffff"><b><a href="{{sixthbox.link}}">{{sixthbox.label}}</a></b></font><br></font></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 130px; left: 20px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{firstbox.description}}<br></font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 130px; left: 229px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{secondbox.description}}<br></font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 130px; left: 435px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{thirdbox.description}}<br></font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 325px; left: 20px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{fourthbox.description}}</font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;top: 325px; left: 230px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{fifthbox.description}}</font><br></div></div></div><div class="componentContainer " style="position: absolute;line-height: normal;position: absolute;line-height: normal;top: 325px; left: 430px; -webkit-transform: ; -moz-transform: ; transform: ; width: px; height: px;"><div class="transformContainer" style="-webkit-transform: scale(1, 1);-moz-transform: scale(1, 1);transform: scale(1, 1)"><div style="font-size: 16px;" class="antialias"><font color="#ffffff">{{sixthbox.description}}</font><br></div></div></div></div>',
    type: 'toc'
    }, {
    src: '',
    type: 'introduction'
    }, {
    src: '',
    type: 'social overview'
    }, {
    src: '',
    type: 'technical seo'
    }];

    var App = function (_React$Component) {
    (0, _inherits3.default)(App, _React$Component);

    function App(props) {
    (0, _classCallCheck3.default)(this, App);

    var _this8 = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(App).call(this, props));

    _this8.state = {
    slides: [{
    id: 'f38c',
    type: 'toc',
    active: true,
    options: {}
    }]
    };
    return _this8;
    }

    (0, _createClass3.default)(App, [{
    key: 'getVariables',
    value: function getVariables(src) {
    return src.match(/{{([\s\S]+?)}}/g).map(function (k) {
    return k.replace(/[^.a-z0-9_\-]/gi, '');
    });
    }
    }, {
    key: 'getSlideSrc',
    value: function getSlideSrc(type) {
    return slides.find(function (s) {
    return s.type === type;
    }).src;
    }
    }, {
    key: 'getActiveSlide',
    value: function getActiveSlide() {
    return this.state.slides.find(function (slide) {
    return slide.active;
    });
    }
    }, {
    key: 'handleOnChange',
    value: function handleOnChange(id, data) {
    var options = data.reduce(function (grp, item) {
    (0, _lodash4.default)(grp, item.keyItem, item.valueItem);
    return grp;
    }, {});
    this.setState({
    slides: this.state.slides.map(function (slide) {
    if (slide.id === id) {
    return (0, _extends3.default)({}, slide, {
    options: options
    });
    }
    return slide;
    })
    });
    }
    }, {
    key: 'handleSetActive',
    value: function handleSetActive(slide) {
    this.setState({
    slides: slides.map(function (s) {
    return (0, _extends3.default)({}, slide, {
    active: slide.id === s.id
    });
    })
    });
    }
    }, {
    key: 'renderEditor',
    value: function renderEditor() {
    var _this9 = this;

    var active = this.getActiveSlide();
    var src = this.getSlideSrc(active.type);
    var rows = this.getVariables(src).map(function (k) {
    return { keyItem: k };
    });
    var addButton = function addButton(handleAddNew) {
    return null;
    };
    return _react2.default.createElement(
    'div',
    null,
    _react2.default.createElement(
    'label',
    null,
    'Type: ',
    _react2.default.createElement(
    'b',
    null,
    active.type
    )
    ),
    _react2.default.createElement(KeyValue, {
    rows: rows,
    customAddButtonRenderer: addButton,
    onChange: function onChange(d) {
    return _this9.handleOnChange(active.id, d);
    } })
    );
    }
    }, {
    key: 'renderSlides',
    value: function renderSlides() {
    var _this10 = this;

    return this.state.slides.map(function (slide) {
    return _this10.renderSlide(slide);
    });
    }
    }, {
    key: 'renderSlide',
    value: function renderSlide(slide) {
    var src = this.getSlideSrc(slide.type);
    var variables = this.getVariables(src);
    var options = (0, _extends3.default)({}, slide.options || {});

    variables.forEach(function (variable) {
    if (!(0, _lodash6.default)(options, variable)) {
    (0, _lodash4.default)(options, variable, variable);
    }
    });
    var content = this.renderSlideContent(src, options);
    var borderColor = slide.active ? 'red' : 'black';
    return _react2.default.createElement(
    _reactBootstrap.Row,
    { key: slide.id, onClick: this.handleSetActive.bind(this, slide) },
    _react2.default.createElement(
    _reactBootstrap.Grid,
    { md: 12, style: { height: '400px', width: '640px', border: 'solid 1px ' + borderColor } },
    _react2.default.createElement('div', { dangerouslySetInnerHTML: { __html: content } })
    )
    );
    }
    }, {
    key: 'renderSlideContent',
    value: function renderSlideContent(text, options) {
    console.log('render', options);
    return (0, _lodash2.default)(text, { interpolate: /{{([\s\S]+?)}}/g })(options);
    }
    }, {
    key: 'render',
    value: function render() {
    var _React$createElement;

    var types = slides.map(function (slide) {
    return slide.type;
    });
    var items = types.map(function (type) {
    return _react2.default.createElement(
    _reactBootstrap.MenuItem,
    { eventKey: type },
    type
    );
    });
    return _react2.default.createElement(
    _reactBootstrap.Grid,
    null,
    _react2.default.createElement(
    _reactBootstrap.Row,
    null,
    _react2.default.createElement(
    _reactBootstrap.Col,
    { md: 3, className: 'editors' },
    this.renderEditor()
    ),
    _react2.default.createElement(
    _reactBootstrap.Col,
    { md: 9, className: 'previews' },
    this.renderSlides()
    )
    ),
    _react2.default.createElement(
    _reactBootstrap.Row,
    null,
    _react2.default.createElement(
    _reactBootstrap.Col,
    null,
    _react2.default.createElement(
    _reactBootstrap.DropdownButton,
    (_React$createElement = { title: 'Add new' }, (0, _defineProperty3.default)(_React$createElement, 'title', 'Add new'), (0, _defineProperty3.default)(_React$createElement, 'key', 'addnew'), (0, _defineProperty3.default)(_React$createElement, 'id', 'addnew'), _React$createElement),
    items
    )
    )
    )
    );
    }
    }]);
    return App;
    }(_react2.default.Component);

    ;

    _reactDom2.default.render(_react2.default.createElement(App, null), document.getElementById('container'));