made with esnextbin
Created
January 18, 2017 16:56
-
-
Save theadam/24f08eb067a8f8c1375ba290ec18d707 to your computer and use it in GitHub Desktop.
esnextbin sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>ESNextbin Sketch</title> | |
<!-- put additional styles and scripts here --> | |
</head> | |
<body> | |
<div id="app"><div id="test"></div></div> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @jsx h */ | |
import { createElement } from 'react'; | |
import { render } from 'react-dom'; | |
const upper = c => c && c === c.toUpperCase(); | |
const mapObj = (obj, fn) => Object.keys(obj).reduce((acc, k) => ({ ...acc, [k]: fn(obj[k]) }), {}); | |
const eventProp = v => v.startsWith('on') && upper(v[2]); | |
function h(tag, jsxProps, ...children) { | |
const props = jsxProps || {}; | |
return dispatch => (state) => { | |
const resolve = sub => { | |
if (isSubscribe(sub)) return sub.run(state); | |
else if (isHandler(sub)) return sub.handle(dispatch); | |
else if (typeof sub === 'function') return sub(dispatch)(state); | |
return sub; | |
} | |
const c = children.map(resolve); | |
const p = mapObj(props, resolve); | |
return createElement(tag, p, c); | |
}; | |
} | |
function startApp(init, reducer, view) { | |
const node = document.createElement('div'); | |
document.body.appendChild(node); | |
let state = init; | |
function dispatch(e) { | |
state = reducer(state, e); | |
render(loadedView(state), node); | |
} | |
const loadedView = view(dispatch) | |
render(loadedView(state), node); | |
} | |
const handlerSym = Symbol('handler'); | |
function Handler(mapper = id => id) { | |
return { | |
[handlerSym]: true, | |
handle: cb => (e) => { | |
cb(mapper(e)); | |
}, | |
map(fn) { | |
return Handler(v => fn(mapper(v))); | |
} | |
} | |
} | |
const target = Handler(e => e.target); | |
const value = target.map(t => t.value); | |
const always = v => Handler(e => v); | |
const subscribeSym = Symbol('subscribe'); | |
function Subscribe(mapper = v => v) { | |
return { | |
[subscribeSym]: true, | |
map(fn) { | |
return Subscribe(v => fn(mapper(v))); | |
}, | |
run(val) { | |
return mapper(val); | |
}, | |
} | |
} | |
const isSubscribe = v => v[subscribeSym] === true; | |
const isHandler = v => v[handlerSym] === true; | |
//////////////////////////////// | |
const init = { value: 0 }; | |
// Actions | |
const Action = { | |
increment(amt) { | |
return { type: Action.increment, value: amt }; | |
} | |
} | |
// Reducer | |
function reducer(state, action) { | |
if (action.type === Action.increment) { | |
return { ...state, value: state.value + 1 }; | |
} | |
return state; | |
} | |
// Queries | |
const val = Subscribe(state => state.value) | |
// View | |
const view = ( | |
<div> | |
<button onClick={always(Action.increment(1))}>Click to increment</button> | |
<div>{val}</div> | |
</div> | |
); | |
startApp(init, reducer, view); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "esnextbin-sketch", | |
"version": "0.0.0", | |
"dependencies": { | |
"react": "15.4.2", | |
"react-dom": "15.4.2", | |
"babel-runtime": "6.20.0" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var _symbol = require('babel-runtime/core-js/symbol'); | |
var _symbol2 = _interopRequireDefault(_symbol); | |
var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); | |
var _defineProperty3 = _interopRequireDefault(_defineProperty2); | |
var _extends3 = require('babel-runtime/helpers/extends'); | |
var _extends4 = _interopRequireDefault(_extends3); | |
var _keys = require('babel-runtime/core-js/object/keys'); | |
var _keys2 = _interopRequireDefault(_keys); | |
var _react = require('react'); | |
var _reactDom = require('react-dom'); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
/** @jsx h */ | |
var upper = function upper(c) { | |
return c && c === c.toUpperCase(); | |
}; | |
var mapObj = function mapObj(obj, fn) { | |
return (0, _keys2.default)(obj).reduce(function (acc, k) { | |
return (0, _extends4.default)({}, acc, (0, _defineProperty3.default)({}, k, fn(obj[k]))); | |
}, {}); | |
}; | |
var eventProp = function eventProp(v) { | |
return v.startsWith('on') && upper(v[2]); | |
}; | |
function h(tag, jsxProps) { | |
for (var _len = arguments.length, children = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | |
children[_key - 2] = arguments[_key]; | |
} | |
var props = jsxProps || {}; | |
return function (dispatch) { | |
return function (state) { | |
var resolve = function resolve(sub) { | |
if (isSubscribe(sub)) return sub.run(state);else if (isHandler(sub)) return sub.handle(dispatch);else if (typeof sub === 'function') return sub(dispatch)(state); | |
return sub; | |
}; | |
var c = children.map(resolve); | |
var p = mapObj(props, resolve); | |
return (0, _react.createElement)(tag, p, c); | |
}; | |
}; | |
} | |
function startApp(init, reducer, view) { | |
var node = document.createElement('div'); | |
document.body.appendChild(node); | |
var state = init; | |
function dispatch(e) { | |
state = reducer(state, e); | |
(0, _reactDom.render)(loadedView(state), node); | |
} | |
var loadedView = view(dispatch); | |
(0, _reactDom.render)(loadedView(state), node); | |
} | |
var handlerSym = (0, _symbol2.default)('handler'); | |
function Handler() { | |
var _ref; | |
var mapper = arguments.length <= 0 || arguments[0] === undefined ? function (id) { | |
return id; | |
} : arguments[0]; | |
return _ref = {}, (0, _defineProperty3.default)(_ref, handlerSym, true), (0, _defineProperty3.default)(_ref, 'handle', function handle(cb) { | |
return function (e) { | |
cb(mapper(e)); | |
}; | |
}), (0, _defineProperty3.default)(_ref, 'map', function map(fn) { | |
return Handler(function (v) { | |
return fn(mapper(v)); | |
}); | |
}), _ref; | |
} | |
var target = Handler(function (e) { | |
return e.target; | |
}); | |
var value = target.map(function (t) { | |
return t.value; | |
}); | |
var always = function always(v) { | |
return Handler(function (e) { | |
return v; | |
}); | |
}; | |
var subscribeSym = (0, _symbol2.default)('subscribe'); | |
function Subscribe() { | |
var _ref2; | |
var mapper = arguments.length <= 0 || arguments[0] === undefined ? function (v) { | |
return v; | |
} : arguments[0]; | |
return _ref2 = {}, (0, _defineProperty3.default)(_ref2, subscribeSym, true), (0, _defineProperty3.default)(_ref2, 'map', function map(fn) { | |
return Subscribe(function (v) { | |
return fn(mapper(v)); | |
}); | |
}), (0, _defineProperty3.default)(_ref2, 'run', function run(val) { | |
return mapper(val); | |
}), _ref2; | |
} | |
var isSubscribe = function isSubscribe(v) { | |
return v[subscribeSym] === true; | |
}; | |
var isHandler = function isHandler(v) { | |
return v[handlerSym] === true; | |
}; | |
//////////////////////////////// | |
var init = { value: 0 }; | |
// Actions | |
var Action = { | |
increment: function increment(amt) { | |
return { type: Action.increment, value: amt }; | |
} | |
}; | |
// Reducer | |
function reducer(state, action) { | |
if (action.type === Action.increment) { | |
return (0, _extends4.default)({}, state, { value: state.value + 1 }); | |
} | |
return state; | |
} | |
// Queries | |
var val = Subscribe(function (state) { | |
return state.value; | |
}); | |
// View | |
var view = h( | |
'div', | |
null, | |
h( | |
'button', | |
{ onClick: always(Action.increment(1)) }, | |
'Click to increment' | |
), | |
h( | |
'div', | |
null, | |
val | |
) | |
); | |
startApp(init, reducer, view); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment