decca
Version:
Render interfaces using pure functions and virtual DOM, kinda
76 lines (55 loc) • 2.56 kB
JavaScript
;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _h = require('virtual-dom/h');
var _h2 = _interopRequireDefault(_h);
var _fix_props = require('./fix_props');
var _fix_props2 = _interopRequireDefault(_fix_props);
var _widget = require('./widget');
var _widget2 = _interopRequireDefault(_widget);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
module.exports = buildPass;
/*
* A rendering pass.
* This closure is responsible for:
*
* - keeping aware of `context` and `state` to be passed down to Components
*
* pass = buildPass(...)
* pass.build(el) // render a component/node
* pass.commitState({...}) // make changes to the state, silently
* pass.setState({...}) // make changes to the state, rerender after
* pass.states // the component states mega-object
*/
function buildPass(context, dispatch, states, commitState, rerender) {
var pass = { build: build, setState: setState, commitState: commitState, states: states };
/*
* Builds from a vnode (`element()` output) to a virtual hyperscript element.
* The `context` and `dispatch` is passed down recursively.
* https://github.com/Matt-Esch/virtual-dom/blob/master/virtual-hyperscript/README.md
*/
function build(el) {
if (typeof el === 'string') return el;
if (typeof el === 'number') return '' + el;
if (typeof el === 'undefined' || el === null) return;
if (Array.isArray(el)) return el.map(build);
var tag = el.tag;
var props = el.props;
var children = el.children;
// Defer to Widget if it's a component
if ((typeof tag === 'undefined' ? 'undefined' : _typeof(tag)) === 'object') {
if (!tag.render) throw new Error('no render() in component');
return new _widget2.default({ component: tag, props: props, children: children }, { context: context, dispatch: dispatch }, pass);
}
return (0, _h2.default)(tag, (0, _fix_props2.default)(props), children.map(build));
}
/*
* Called by Components (via Widget). Queues up state changes, and updates it
* when it can.
*/
function setState(componentId) {
var state = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
commitState(componentId, state);
rerender();
}
return pass;
}