react-motherboard
Version:
A simple flux-like concept react component container framework.
168 lines (144 loc) • 4.37 kB
JavaScript
var React = require('react');
var Motherboard = function(options) {
this.layout = null;
this.chipInstances = []; // [{name: '', instance: null}]
this.ACTIONS = options.ACTIONS || {};
this.SLOTS = options.SLOTS || {};
this.callbacks = {};
console.log('new Motherboard', this.ACTIONS, this.SLOTS);
};
Motherboard.prototype.register = function(actionType, cb) {
if(this.callbacks[actionType])
this.callbacks[actionType].push(cb);
else
this.callbacks[actionType] = [cb];
};
Motherboard.prototype.emit = function(action) {
this.callbacks[action.type].forEach(function(cb) {
cb(action.payload);
});
};
Motherboard.prototype.addLayout = function(layout /* ReactClass */) {
console.log('MB.addLayout', layout);
// inject motherboard reference to layout
layout.prototype.MB = this;
var didMountFunc = layout.prototype.componentDidMount,
that = this;
layout.prototype.componentDidMount = function() {
var layout_this = this;
didMountFunc();
that.chipInstances.forEach(function(instance) {
var name = instance.name;
React.render(instance.instance, layout_this.refs[name].getDOMNode());
});
};
this.layout = layout;
};
Motherboard.prototype.addChip = function(name /* slot name */, chip /* ReactElement */) {
console.log('MB.addChip', name, chip);
if(this.SLOTS[name]) {
// inject motherboard reference to chip instance
var reactType = chip.type;
reactType.prototype.MB = this;
this.chipInstances.push({name: name, instance: chip});
} else {
console.err('MB', 'can not find the slot: ' + name);
}
};
Motherboard.prototype.run = function(mountNode) {
console.log('MB.run');
React.render(React.createElement(this.layout), mountNode);
};
// test code
Motherboard.test = function() {
console.log('running test');
var mb = new Motherboard({
ACTIONS: {CLICK: 'CLICK', STOREUPDATE: 'STOREUPDATE'},
SLOTS: {SIDEBAR: 'SIDEBAR', CONTENT: 'CONTENT', STORE: 'STORE'},
});
var Sidebar = React.createClass({displayName: "Sidebar",
handleClick: function(e) {
console.log('Sidebar handleClick', this.MB.ACTIONS.CLICK);
this.MB.emit({type: this.MB.ACTIONS.CLICK, payload: 'hello'});
},
render: function() {
return (
React.createElement("div", null,
React.createElement("button", {onClick: this.handleClick}, this.props.value)
)
);
}
});
var Content = React.createClass({displayName: "Content",
getInitialState: function() {
return {
content: 'placeholder'
};
},
componentDidMount: function() {
this.MB.register(this.MB.ACTIONS.CLICK, function(payload) {
console.log('i got it!!! ' + payload);
});
var that = this;
this.MB.register(this.MB.ACTIONS.STOREUPDATE, function(payload) {
that.setState({content: payload});
});
},
render: function() {
return (
React.createElement("div", null,
React.createElement("p", null, this.state.content)
)
);
}
});
var Store = React.createClass({displayName: "Store",
getInitialState: function() {
return {
store: ' '
};
},
componentDidMount: function() {
var that = this;
this.MB.register(this.MB.ACTIONS.CLICK, function(payload) {
that.setState({store: that.state.store + ',' + payload});
that.MB.emit({type: that.MB.ACTIONS.STOREUPDATE, payload: that.state.store});
});
},
render: function() {
return (
React.createElement("div", null)
);
}
});
mb.addLayout(React.createClass({
componentDidMount: function() {
console.log('layout existing componentDidMount');
},
render: function() {
var style = {
border: '1px solid black',
padding: '5px'
},
layoutStyle = {
display: 'flex',
flexDirection: 'row'
};
return (
React.createElement("div", null,
React.createElement("h4", null, "motherboard layout"),
React.createElement("div", {style: layoutStyle},
React.createElement("div", {style: style, ref: mb.SLOTS.SIDEBAR}),
React.createElement("div", {style: style, ref: mb.SLOTS.CONTENT}),
React.createElement("div", {ref: mb.SLOTS.STORE})
)
)
);
}
}));
mb.addChip(mb.SLOTS.SIDEBAR, React.createElement(Sidebar, {value: "new button 2"}));
mb.addChip(mb.SLOTS.CONTENT, React.createElement(Content, null));
mb.addChip(mb.SLOTS.STORE, React.createElement(Store, null));
mb.run(mountNode);
}
module.exports = Motherboard;