microcosm
Advanced tools
Comparing version 5.2.0 to 6.0.0
# Changelog | ||
### 6.0.0 | ||
6.0.0 is the second effort to reduce the surface area of the Microcosm API. | ||
- Removed `Upstream` and `Downstream` mixins. They used the | ||
undocumented context API and introduced some complexity in testing | ||
- `Microcosm::send` is now `Microcosm::push` | ||
- `Microcosm::push` is now `Microcosm::replace` | ||
- `Microcosm::dispatch` and `Microcosm::commit` are now private. These | ||
are important methods that should not be overridden | ||
### 5.2.0 | ||
@@ -4,0 +15,0 @@ |
@@ -1,2 +0,2 @@ | ||
module.exports=function(t){function n(e){if(r[e])return r[e].exports;var i=r[e]={exports:{},id:e,loaded:!1};return t[e].call(i.exports,i,i.exports,n),i.loaded=!0,i.exports}var r={};return n.m=t,n.c=r,n.p="",n(0)}([function(t,n,r){"use strict";n.__esModule=!0;var e=r(12);n.tag=e,n["default"]=r(4)},function(t){"use strict";function n(t,n){if(!t){var r=new Error(n);throw r.framesToPop=1,r}}t.exports=n},function(t,n,r){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},i=e(r(1));t.exports={validate:function(t){i("function"==typeof t,"Action "+t+" is not callable, actions should be functions")}}},function(t){"use strict";function n(t,n){var r=void 0===arguments[2]?{}:arguments[2],e=Object.keys(t);return e.reduce(function(r,e){return r[e]=n(t[e],e),r},r)}t.exports=n},function(t,n,r){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},i=Object.assign||function(t){for(var n=1;n<arguments.length;n++){var r=arguments[n];for(var e in r)Object.prototype.hasOwnProperty.call(r,e)&&(t[e]=r[e])}return t},o=function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")},u=e(r(2)),s=e(r(5)),a=e(r(6)),c=e(r(1)),f=e(r(7)),l=e(r(8)),p=e(r(9)),h=e(r(3)),d=e(r(10)),v=e(r(11)),g=function(){function t(){o(this,t),p(this),this._state={},this._stores={},this._plugins=[]}return t.prototype.push=function(t){this.commit(this.deserialize(t))},t.prototype.pull=function(t,n){for(var r=arguments.length,e=Array(r>2?r-2:0),i=2;r>i;i++)e[i-2]=arguments[i];var o=this._state[t];return"function"==typeof n?n.call.apply(n,[this,o].concat(e)):o},t.prototype.commit=function(t){this._state=t,this.emit()},t.prototype.prepare=function(t){for(var n,r=arguments.length,e=Array(r>1?r-1:0),i=1;r>i;i++)e[i-1]=arguments[i];return u.validate(t),(n=this.send).bind.apply(n,[this,t].concat(e))},t.prototype.send=function(t){var n=function(){return t.apply(this,arguments)};return n.toString=function(){return t.toString()},n}(function(t){for(var n=arguments.length,r=Array(n>1?n-1:0),e=1;n>e;e++)r[e-1]=arguments[e];return v.apply(void 0,[this,t].concat(r))}),t.prototype.dispatch=function(t,n){var r=this,e=d(this._stores,function(n){return t in n});return Object.keys(e).length>0&&!function(){var i=f(r._state),o=h(e,function(r){return r[t](i[r],n)},i);r.commit(o)}(),n},t.prototype.addPlugin=function(t,n){s.validate(t),this._plugins.push([t,n])},t.prototype.addStore=function(t){var n=i({},a,t);c(!this._stores[t],'Tried to add "'+t+'" but it is not unique'),this._stores[n]=n},t.prototype.serialize=function(){var t=this;return h(this._stores,function(n){return n.serialize(t.pull(n))})},t.prototype.deserialize=function(){var t=void 0===arguments[0]?{}:arguments[0];return h(this._stores,function(n){return n.deserialize(t[n])})},t.prototype.toJSON=function(){return this.serialize()},t.prototype.toObject=function(){return d(this._state,function(){return!0})},t.prototype.start=function(){for(var t=arguments.length,n=Array(t),r=0;t>r;r++)n[r]=arguments[r];this._state=h(this._stores,function(t){return t.getInitialState()}),l(this._plugins,this,function(){n.forEach(function(t){return t()})})},t}();t.exports=g},function(t,n,r){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},i=e(r(1));t.exports={validate:function(t){i("register"in t,"Plugins must have a register method.")}}},function(t){"use strict";t.exports={getInitialState:function(){return void 0},serialize:function(t){return t},deserialize:function(){var t=void 0===arguments[0]?this.getInitialState():arguments[0];return t},toString:function(){throw new Error("Stores must implement a toString() method")}}},function(t){"use strict";t.exports=function(t){return Object.create(t)}},function(t){"use strict";function n(t,i,o){var u=e(t),s=u[0],a=u.slice(1);if(!s)return o();var c=r(s,2),f=c[0],l=c[1];f.register(i,l,function(t){if(t)throw t;n(a,i,o)})}var r=function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t)){for(var r,e=[],i=t[Symbol.iterator]();!(r=i.next()).done&&(e.push(r.value),!n||e.length!==n););return e}throw new TypeError("Invalid attempt to destructure non-iterable instance")},e=function(t){return Array.isArray(t)?t:Array.from(t)};t.exports=n},function(t){"use strict";function n(){var t=void 0===arguments[0]?{}:arguments[0],n=[];return t.ignore=function(t){n=n.filter(function(n){return n!==t})},t.listen=function(t){n.push(t)},t.emit=function(){for(var t=0;t<n.length;t++)n[t].call(this)},t}t.exports=n},function(t){"use strict";t.exports=function(t,n){var r={};for(var e in t)n(t[e])&&(r[e]=t[e]);return r}},function(t,n,r){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},i=e(r(2));t.exports=function(t,n){for(var r=arguments.length,e=Array(r>2?r-2:0),o=2;r>o;o++)e[o-2]=arguments[o];i.validate(n);var u=n.apply(t,e);return u instanceof Promise?u.then(function(r){return t.dispatch(n,r)}):t.dispatch(n,u)}},function(t,n,r){"use strict";function e(t){return"function"==typeof t}function i(t,n){var r=t.bind(null),e="_"+n+"_"+s++;return r.toString=function(){return e},r}var o=function(t){return t&&t.__esModule?t["default"]:t},u=o(r(3)),s=0;t.exports=function(t){return u(t,function(t,n){return e(t)?i(t,n):t})}}]); | ||
module.exports=function(t){function r(e){if(n[e])return n[e].exports;var i=n[e]={exports:{},id:e,loaded:!1};return t[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}var n={};return r.m=t,r.c=n,r.p="",r(0)}([function(t,r,n){"use strict";r.__esModule=!0;var e=n(11);r.tag=e,r["default"]=n(4)},function(t){"use strict";function r(t,r){if(!t){var n=new Error(r);throw n.framesToPop=1,n}}t.exports=r},function(t){"use strict";function r(t,r){var n=void 0===arguments[2]?{}:arguments[2],e=Object.keys(t);return e.reduce(function(n,e){return n[e]=r(t[e],e),n},n)}t.exports=r},function(t,r,n){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},i=e(n(1));t.exports={validate:function(t){i("function"==typeof t,"Action "+t+" is not callable, actions should be functions")}}},function(t,r,n){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},i=Object.assign||function(t){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var e in n)Object.prototype.hasOwnProperty.call(n,e)&&(t[e]=n[e])}return t},o=function(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")},u=e(n(3)),s=e(n(5)),a=e(n(6)),c=e(n(1)),f=e(n(7)),p=e(n(8)),l=e(n(9)),h=e(n(2)),d=e(n(10)),v=function(){function t(){o(this,t),l(this),this._state={},this._stores={},this._plugins=[]}return t.prototype.push=function(t){for(var r=this,n=arguments.length,e=Array(n>1?n-1:0),i=1;n>i;i++)e[i-1]=arguments[i];u.validate(t);var o=t.apply(void 0,e);return o instanceof Promise?o.then(function(n){return r._dispatch(t,n)}):this._dispatch(t,o)},t.prototype.pull=function(t,r){for(var n=arguments.length,e=Array(n>2?n-2:0),i=2;n>i;i++)e[i-2]=arguments[i];var o=this._state[t];return"function"==typeof r?r.call.apply(r,[this,o].concat(e)):o},t.prototype.prepare=function(t){for(var r,n=arguments.length,e=Array(n>1?n-1:0),i=1;n>i;i++)e[i-1]=arguments[i];return u.validate(t),(r=this.push).bind.apply(r,[this,t].concat(e))},t.prototype.replace=function(t){this._commit(this.deserialize(t))},t.prototype._commit=function(t){this._state=t,this.emit()},t.prototype._dispatch=function(t,r){var n=this,e=d(this._stores,function(r){return t in r});return Object.keys(e).length>0&&!function(){var i=f(n._state),o=h(e,function(n){return n[t](i[n],r)},i);n._commit(o)}(),r},t.prototype.addPlugin=function(t,r){s.validate(t),this._plugins.push([t,r])},t.prototype.addStore=function(t){var r=i({},a,t);c(!this._stores[t],'Tried to add "'+t+'" but it is not unique'),this._stores[r]=r},t.prototype.serialize=function(){var t=this;return h(this._stores,function(r){return r.serialize(t.pull(r))})},t.prototype.deserialize=function(){var t=void 0===arguments[0]?{}:arguments[0];return h(this._stores,function(r){return r.deserialize(t[r])})},t.prototype.toJSON=function(){return this.serialize()},t.prototype.toObject=function(){return d(this._state,function(){return!0})},t.prototype.start=function(){for(var t=arguments.length,r=Array(t),n=0;t>n;n++)r[n]=arguments[n];this._state=h(this._stores,function(t){return t.getInitialState()}),p(this._plugins,this,function(){r.forEach(function(t){return t()})})},t}();t.exports=v},function(t,r,n){"use strict";var e=function(t){return t&&t.__esModule?t["default"]:t},i=e(n(1));t.exports={validate:function(t){i("register"in t,"Plugins must have a register method.")}}},function(t){"use strict";t.exports={getInitialState:function(){return void 0},serialize:function(t){return t},deserialize:function(){var t=void 0===arguments[0]?this.getInitialState():arguments[0];return t},toString:function(){throw new Error("Stores must implement a toString() method")}}},function(t){"use strict";t.exports=function(t){return Object.create(t)}},function(t){"use strict";function r(t,i,o){var u=e(t),s=u[0],a=u.slice(1);if(!s)return o();var c=n(s,2),f=c[0],p=c[1];f.register(i,p,function(t){if(t)throw t;r(a,i,o)})}var n=function(t,r){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t)){for(var n,e=[],i=t[Symbol.iterator]();!(n=i.next()).done&&(e.push(n.value),!r||e.length!==r););return e}throw new TypeError("Invalid attempt to destructure non-iterable instance")},e=function(t){return Array.isArray(t)?t:Array.from(t)};t.exports=r},function(t){"use strict";function r(){var t=void 0===arguments[0]?{}:arguments[0],r=[];return t.ignore=function(t){r=r.filter(function(r){return r!==t})},t.listen=function(t){r.push(t)},t.emit=function(){for(var t=0;t<r.length;t++)r[t].call(this)},t}t.exports=r},function(t){"use strict";t.exports=function(t,r){var n={};for(var e in t)r(t[e])&&(n[e]=t[e]);return n}},function(t,r,n){"use strict";function e(t){return"function"==typeof t}function i(t,r){var n=t.bind(null),e="_"+r+"_"+s++;return n.toString=function(){return e},n}var o=function(t){return t&&t.__esModule?t["default"]:t},u=o(n(2)),s=0;t.exports=function(t){return u(t,function(t,r){return e(t)?i(t,r):t})}}]); | ||
//# sourceMappingURL=Microcosm.js.map |
@@ -10,7 +10,8 @@ # API Cheatsheet | ||
Data Operations | ||
State Management | ||
+--------------+ | ||
commit - Assign a new state, trigger an event | ||
pull - Provided a key, return that entry in the state object | ||
push - Replace state with the result of deserializing a set of data | ||
pull - Provided a key, return that entry in the state object | ||
push - Queue up an action, potentially changing data | ||
prepare - Partially apply the `push` method | ||
replace - Replace state with the result of deserializing a set of data | ||
@@ -24,8 +25,2 @@ Serialization | ||
Message passing | ||
+--------------+ | ||
dispatch - Send an action and payload to all stores | ||
prepare - Partially apply the `send` method | ||
send - Given a set of parameters, execute an action and forward that result to `dispatch` | ||
Events | ||
@@ -37,3 +32,3 @@ +--------------+ | ||
Install | ||
Configure | ||
+--------------+ | ||
@@ -40,0 +35,0 @@ addPlugin - Append an entry into the list of known plugins |
@@ -24,9 +24,11 @@ # Microcosm | ||
class MyApp extends Microcosm { | ||
push(data) { | ||
// Tells the microcosm how it should handle data injected from | ||
// sources. | ||
push(fn, ...params) { | ||
// Responsible for pushing an action through the system. | ||
// `send`. | ||
// | ||
// By default, it will clean the data with `deserialize` and | ||
// then override the existing data set with the new values | ||
// If `fn(...params)` returns a promise, it will wait for this | ||
// promise to resolve. | ||
} | ||
pull(key) { | ||
@@ -36,26 +38,16 @@ // If a key is provided, return that entry in state. Otherwise | ||
} | ||
clone() { | ||
// return an object who's prototype is the previous state. This is | ||
// used for revisions to data | ||
} | ||
commit(next) { | ||
// Given a next state, only trigger an event if state actually | ||
// changed | ||
} | ||
prepare(fn, ...params) { | ||
// Returns a partially applied version of `send`. Useful | ||
// Returns a partially applied version of `push`. Useful | ||
// for concise callbacks in React components | ||
} | ||
send(fn, ...params) { | ||
// Responsible for pushing an action through the system. | ||
// `send`. | ||
replace(data) { | ||
// Tells the microcosm how it should handle data injected from | ||
// sources. | ||
// | ||
// If `fn(...params)` returns a promise, it will wait for this | ||
// promise to resolve. | ||
// By default, it will clean the data with `deserialize` and | ||
// then override the existing data set with the new values | ||
} | ||
dispatch(action, body) { | ||
// Multicasts an action to all known stores, reducing down the | ||
// resulting callbacks into a change set. If state changes, it | ||
// will trigger a change event after assigning the new state | ||
} | ||
addStore(store) { | ||
@@ -66,2 +58,3 @@ // Folds over a default interface and then assigns | ||
} | ||
addPlugin(plugin) { | ||
@@ -71,2 +64,3 @@ // Verifies required api and adds available plugin. This will be | ||
} | ||
serialize(state) { | ||
@@ -79,2 +73,3 @@ // Transforms the internal state of a microcosm into a digestable | ||
} | ||
deserialize(state) { | ||
@@ -85,11 +80,15 @@ // Defines how to clean data before it is injected into the | ||
} | ||
toJSON() { | ||
// A default implementation of serialization. Just returns `this.serialize()` | ||
} | ||
toObject() { | ||
// Return a flat copy of state | ||
} | ||
start(...callbacks) { | ||
// Setup initial state, run plugins, then execute callbacks | ||
} | ||
} | ||
@@ -96,0 +95,0 @@ ``` |
@@ -14,3 +14,2 @@ import App from '../App' | ||
app = new App() | ||
app.start(done) | ||
@@ -23,3 +22,3 @@ }) | ||
beforeEach(function() { | ||
app.send(ListActions.add, { name }) | ||
app.push(ListActions.add, { name }) | ||
}) | ||
@@ -37,4 +36,4 @@ | ||
beforeEach(function() { | ||
app.send(ListActions.add, { name }) | ||
app.send(ListActions.remove, app.pull(Lists)[0].id) | ||
app.push(ListActions.add, { name }) | ||
app.push(ListActions.remove, app.pull(Lists)[0].id) | ||
}) | ||
@@ -52,4 +51,4 @@ | ||
beforeEach(function() { | ||
app.send(ListActions.add, { name: 'parent' }) | ||
app.send(ItemActions.add, { name, list: app.pull(Lists)[0] }) | ||
app.push(ListActions.add, { name: 'parent' }) | ||
app.push(ItemActions.add, { name, list: app.pull(Lists)[0] }) | ||
}) | ||
@@ -67,5 +66,5 @@ | ||
beforeEach(function() { | ||
app.send(ListActions.add, { name: 'parent' }) | ||
app.send(ItemActions.add, { name, list: app.pull(Lists)[0] }) | ||
app.send(ItemActions.remove, app.pull(Items)[0].id) | ||
app.push(ListActions.add, { name: 'parent' }) | ||
app.push(ItemActions.add, { name, list: app.pull(Lists)[0] }) | ||
app.push(ItemActions.remove, app.pull(Items)[0].id) | ||
}) | ||
@@ -83,5 +82,5 @@ | ||
beforeEach(function() { | ||
app.send(ListActions.add, { name: 'parent' }) | ||
app.send(ItemActions.add, { name, list: app.pull(Lists)[0] }) | ||
app.send(ListActions.remove, app.pull(Lists)[0].id) | ||
app.push(ListActions.add, { name: 'parent' }) | ||
app.push(ItemActions.add, { name, list: app.pull(Lists)[0] }) | ||
app.push(ListActions.remove, app.pull(Lists)[0].id) | ||
}) | ||
@@ -99,3 +98,3 @@ | ||
beforeEach(function() { | ||
app.send(RouteActions.set, params) | ||
app.push(RouteActions.set, params) | ||
}) | ||
@@ -102,0 +101,0 @@ |
import AddItem from './AddItem' | ||
import Downstream from 'Downstream' | ||
import ListActions from 'actions/lists' | ||
import React from 'react' | ||
import classNames from 'classnames' | ||
@@ -10,3 +10,5 @@ let randomColor = () => '#'+Math.floor(Math.random()*16777215).toString(16); | ||
mixins: [ Downstream ], | ||
propTypes: { | ||
app : React.PropTypes.object.isRequired | ||
}, | ||
@@ -20,17 +22,11 @@ getInitialState() { | ||
render() { | ||
let className = 'bottomsheet' | ||
let { active, onExit } = this.props | ||
if (this.props.active) { | ||
className += ' is-active' | ||
} | ||
return ( | ||
<div className={ className }> | ||
<div className="bottomsheet__blackout" onClick={ this.props.onExit } /> | ||
<div className={ classNames('bottomsheet', { 'is-active' : active }) }> | ||
<div className="bottomsheet__blackout" onClick={ onExit } /> | ||
<div className="container relative pad-2-top pad-4-bottom fill-white shadow-1 radius-2"> | ||
<AddItem onSubmit={ this._onAddList } /> | ||
<label className="label">Background Color</label> | ||
<input type="color" | ||
value={ this.state.color } | ||
onChange={ this._onColorChange } /> | ||
<input type="color" value={ this.state.color } onChange={ this._onChange } /> | ||
</div> | ||
@@ -41,3 +37,3 @@ </div> | ||
_onColorChange({ target }) { | ||
_onChange({ target }) { | ||
this.setState({ color: target.value }) | ||
@@ -47,7 +43,9 @@ }, | ||
_onAddList(name) { | ||
this.send(ListActions.add, { name, color: this.state.color }) | ||
let { app, onExit } = this.props | ||
app.push(ListActions.add, { name, color: this.state.color }) | ||
this.setState({ color: randomColor() }) | ||
this.props.onExit() | ||
onExit() | ||
} | ||
@@ -54,0 +52,0 @@ |
import DeleteIcon from 'icons/delete' | ||
import Downstream from 'Downstream' | ||
import Icon from 'fragments/Icon' | ||
import Link from 'fragments/Link' | ||
import React from 'react' | ||
import ListActions from 'actions/lists' | ||
let ListItem = React.createClass({ | ||
mixins: [ Downstream ], | ||
propTypes: { | ||
list: React.PropTypes.object.isRequired | ||
count : React.PropTypes.number.isRequired, | ||
list : React.PropTypes.object.isRequired, | ||
onRemove : React.PropTypes.func.isRequired | ||
}, | ||
render() { | ||
let { list, items } = this.props | ||
let { list, count } = this.props | ||
let { color:background, contrast:color, name, id } = list | ||
@@ -22,5 +21,3 @@ | ||
<Link href={ `/list/${id}` } className="list__item__link flex"> | ||
<span className="list__item__counter" style={{ background, color }}> | ||
{ items.length } | ||
</span> | ||
<span className="list__item__counter" style={{ background, color }}>{ count }</span> | ||
<span className="flex-grow">{ name }</span> | ||
@@ -34,3 +31,3 @@ </Link> | ||
_onRemoveItem() { | ||
this.send(ListActions.remove, this.props.list.id) | ||
this.props.onRemove(this.props.list.id) | ||
} | ||
@@ -37,0 +34,0 @@ }) |
import AddItem from './AddItem' | ||
import Downstream from 'Downstream' | ||
import ItemActions from 'actions/items' | ||
@@ -7,15 +6,15 @@ import React from 'react' | ||
let TaskList = React.createClass({ | ||
mixins: [ Downstream ], | ||
export default React.createClass({ | ||
propTypes: { | ||
list: React.PropTypes.object.isRequired | ||
app : React.PropTypes.object.isRequired, | ||
list : React.PropTypes.object.isRequired | ||
}, | ||
getItem(item) { | ||
return (<TaskListItem key={ item.id } item={ item } onDelete={ this._onRemoveItem } />) | ||
return (<TaskListItem key={ item.id } item={ item } onRemove={ this._onRemoveItem } />) | ||
}, | ||
render() { | ||
let { color, id, name } = this.props.list | ||
let { items, list } = this.props | ||
@@ -30,3 +29,3 @@ return ( | ||
<ul className="list"> | ||
{ this.props.items.map(this.getItem) } | ||
{ items.map(this.getItem) } | ||
</ul> | ||
@@ -39,11 +38,11 @@ </div> | ||
_onAddItem(name) { | ||
this.send(ItemActions.add, { name, list: this.props.list}) | ||
let { app, list } = this.props | ||
app.push(ItemActions.add, { name, list }) | ||
}, | ||
_onRemoveItem(item) { | ||
this.send(ItemActions.remove, item.id) | ||
this.props.app.push(ItemActions.remove, item.id) | ||
} | ||
}) | ||
export default TaskList |
@@ -8,3 +8,4 @@ import DeleteIcon from 'icons/delete' | ||
propTypes: { | ||
item : React.PropTypes.object.isRequired | ||
item : React.PropTypes.object.isRequired, | ||
onRemove : React.PropTypes.func.isRequired | ||
}, | ||
@@ -24,3 +25,3 @@ | ||
_onRemoveItem() { | ||
this.props.onDelete(this.props.item) | ||
this.props.onRemove(this.props.item) | ||
} | ||
@@ -27,0 +28,0 @@ }) |
@@ -1,3 +0,2 @@ | ||
import React from 'react' | ||
import Upstream from 'Upstream' | ||
import React from 'react' | ||
@@ -10,6 +9,6 @@ let Layout = React.createClass({ | ||
render() { | ||
let { items, lists, route } = this.props | ||
let { app, items, lists, route } = this.props | ||
return React.createElement(route.handler, { | ||
app : this.props.app, | ||
app : app, | ||
items : items, | ||
@@ -16,0 +15,0 @@ lists : lists, |
@@ -1,3 +0,5 @@ | ||
import ListItem from 'fragments/ListItem' | ||
import React from 'react' | ||
import ListActions from 'actions/lists' | ||
import ListItem from 'fragments/ListItem' | ||
import React from 'react' | ||
import count from 'count' | ||
@@ -12,5 +14,9 @@ let Body = React.createClass({ | ||
getList(list) { | ||
let children = this.props.items.filter(i => i.list === list.id) | ||
let { app } = this.props | ||
return (<ListItem key={ list.id } items={ children } list={ list } />) | ||
return ( | ||
<ListItem key={ list.id } | ||
count={ app.pull('items', count, list) } | ||
list={ list } | ||
onRemove={ this._onRemoveList } />) | ||
}, | ||
@@ -23,3 +29,3 @@ | ||
<ul className="list"> | ||
{ this.props.lists.map(this.getList) } | ||
{ this.props.app.pull('lists').map(this.getList) } | ||
</ul> | ||
@@ -29,2 +35,6 @@ </div> | ||
) | ||
}, | ||
_onRemoveList(id) { | ||
this.props.app.push(ListActions.remove, id) | ||
} | ||
@@ -31,0 +41,0 @@ |
@@ -5,8 +5,6 @@ import AddList from 'fragments/AddList' | ||
import React from 'react' | ||
import Upstream from 'Upstream' | ||
let Home = React.createClass({ | ||
mixins: [ Upstream ], | ||
propTypes: { | ||
app : React.PropTypes.object.isRequired, | ||
lists : React.PropTypes.array.isRequired, | ||
@@ -23,7 +21,9 @@ items : React.PropTypes.array.isRequired | ||
render() { | ||
let { app, lists, items } = this.props | ||
return ( | ||
<main role="main"> | ||
<Banner onToggle={ this._onToggle } /> | ||
<Body lists={ this.props.lists } items={ this.props.items } /> | ||
<AddList active={ this.state.openCreate } onExit={ this._onToggle } /> | ||
<Body app={ app } lists={ lists } items={ items } /> | ||
<AddList app={ app } active={ this.state.openCreate } onExit={ this._onToggle } /> | ||
</main> | ||
@@ -30,0 +30,0 @@ ) |
@@ -7,3 +7,3 @@ import BackIcon from 'icons/arrow-back' | ||
let Banner = React.createClass({ | ||
export default React.createClass({ | ||
@@ -18,4 +18,6 @@ propTypes: { | ||
let { color, contrast, name } = list | ||
return ( | ||
<header className="ruled-bottom" style={{ background: list.color, color: list.contrast }}> | ||
<header className="ruled-bottom" style={{ background: color, color: contrast }}> | ||
<div className="flex pad-2"> | ||
@@ -28,3 +30,3 @@ <div className="flex-grow"> | ||
<div className="container pad-2-top pad-7-bottom"> | ||
<h1 className="type-display">{ list.name }</h1> | ||
<h1 className="type-display">{ name }</h1> | ||
</div> | ||
@@ -36,3 +38,1 @@ </header> | ||
}) | ||
export default Banner |
@@ -5,13 +5,13 @@ import Banner from './Banner' | ||
import TaskList from 'fragments/TaskList' | ||
import Upstream from 'Upstream' | ||
import find from 'find' | ||
import children from 'children' | ||
import findBy from 'findBy' | ||
import page from 'page' | ||
let Show = React.createClass({ | ||
mixins: [ Upstream ], | ||
export default React.createClass({ | ||
render() { | ||
let { items, lists, params, props } = this.props | ||
let { app, params } = this.props | ||
let list = find(lists, i => i.id == params.id) | ||
let list = app.pull('lists', findBy, params.id) | ||
let items = app.pull('items', children, list) | ||
@@ -21,3 +21,3 @@ return ( | ||
<Banner list={ list } onRemove={ this._onRemoveList } /> | ||
<TaskList list={ list } items={ items.filter(i => i.list == list.id) } /> | ||
<TaskList app={ app } list={ list } items={ items } /> | ||
</main> | ||
@@ -28,3 +28,6 @@ ) | ||
_onRemoveList() { | ||
this.send(ListActions.remove, this.props.params.id) | ||
let { app, params } = this.props | ||
app.push(ListActions.remove, params.id) | ||
page('/') | ||
@@ -34,3 +37,1 @@ } | ||
}) | ||
export default Show |
@@ -26,3 +26,3 @@ /** | ||
app.listen(() => this.save(app)) | ||
app.push(this.fetch()) | ||
app.replace(this.fetch()) | ||
@@ -29,0 +29,0 @@ next() |
{ | ||
"name": "microcosm", | ||
"version": "5.2.0", | ||
"version": "6.0.0", | ||
"description": "A functional flux architecture", | ||
@@ -24,2 +24,3 @@ "main": "dist/Microcosm.js", | ||
"chai": "^2.1.2", | ||
"classnames": "^1.2.0", | ||
"coveralls": "^2.11.2", | ||
@@ -26,0 +27,0 @@ "css-loader": "^0.9.0", |
@@ -14,5 +14,5 @@ import Action from './fixtures/Action' | ||
describe('Microcosm::push', function() { | ||
describe('Microcosm::replace', function() { | ||
it ('runs deserialize before committing results', function() { | ||
app.push({ dummy: 'test' }) | ||
app.replace({ dummy: 'test' }) | ||
app.pull(DummyStore).should.equal('test') | ||
@@ -23,3 +23,3 @@ }) | ||
app.listen(done) | ||
app.push({ dummy: 'test' }) | ||
app.replace({ dummy: 'test' }) | ||
}) | ||
@@ -46,5 +46,5 @@ }) | ||
describe('Microcosm::commit', function() { | ||
describe('Microcosm::_commit', function() { | ||
it ('assigns new state', function() { | ||
app.commit({ foo: 'bar' }) | ||
app._commit({ foo: 'bar' }) | ||
app.pull('foo').should.equal('bar') | ||
@@ -55,3 +55,3 @@ }) | ||
app.listen(done) | ||
app.commit('test') | ||
app._commit('test') | ||
}) | ||
@@ -61,3 +61,3 @@ }) | ||
describe('Microcosm::prepare', function() { | ||
it ('partially apply Microcosm::send', function() { | ||
it ('partially apply Microcosm::push', function() { | ||
let add = (a=0, b=0) => a + b | ||
@@ -79,7 +79,7 @@ | ||
describe('Microcosm:send', function() { | ||
describe('Microcosm:push', function() { | ||
it ('sends a messages to the dispatcher', function() { | ||
sinon.spy(app, 'dispatch') | ||
app.send(Action) | ||
app.dispatch.should.have.been.calledWith(Action, true) | ||
sinon.spy(app, '_dispatch') | ||
app.push(Action) | ||
app._dispatch.should.have.been.calledWith(Action, true) | ||
}) | ||
@@ -90,6 +90,6 @@ | ||
sinon.spy(app, 'dispatch') | ||
sinon.spy(app, '_dispatch') | ||
app.send(Async).then(function() { | ||
app.dispatch.should.have.been.calledWith(Async, true) | ||
app.push(Async).then(function() { | ||
app._dispatch.should.have.been.calledWith(Async, true) | ||
done() | ||
@@ -101,3 +101,3 @@ }) | ||
try { | ||
app.send(undefined) | ||
app.push(undefined) | ||
} catch(x) { | ||
@@ -109,3 +109,3 @@ done() | ||
describe('Microcosm::dispatch', function() { | ||
describe('Microcosm::_dispatch', function() { | ||
let local; | ||
@@ -124,3 +124,3 @@ | ||
local.dispatch(Action) | ||
local._dispatch(Action) | ||
}) | ||
@@ -130,3 +130,3 @@ | ||
local.listen(done) | ||
local.dispatch('respond') | ||
local._dispatch('respond') | ||
}) | ||
@@ -203,3 +203,3 @@ | ||
it ('can turn into a flat object', function() { | ||
app.commit(Object.create({ foo: 'bar' })) | ||
app._commit(Object.create({ foo: 'bar' })) | ||
app.toObject().should.have.property('foo', 'bar') | ||
@@ -206,0 +206,0 @@ }) |
@@ -16,3 +16,2 @@ /** | ||
import remapIf from './remapIf' | ||
import send from './send' | ||
@@ -29,4 +28,14 @@ export default class Microcosm { | ||
push(data) { | ||
this.commit(this.deserialize(data)) | ||
push(signal, ...params) { | ||
Action.validate(signal) | ||
const request = signal(...params) | ||
// Actions some times return promises. When this happens, wait for | ||
// them to resolve before moving on | ||
if (request instanceof Promise) { | ||
return request.then(body => this._dispatch(signal, body)) | ||
} | ||
return this._dispatch(signal, request) | ||
} | ||
@@ -39,17 +48,17 @@ | ||
commit(next) { | ||
this._state = next | ||
this.emit() | ||
} | ||
prepare(fn, ...buffer) { | ||
Action.validate(fn) | ||
return this.send.bind(this, fn, ...buffer) | ||
return this.push.bind(this, fn, ...buffer) | ||
} | ||
send(fn, ...params) { | ||
return send(this, fn, ...params) | ||
replace(data) { | ||
this._commit(this.deserialize(data)) | ||
} | ||
dispatch(action, body) { | ||
_commit(next) { | ||
this._state = next | ||
this.emit() | ||
} | ||
_dispatch(action, body) { | ||
let actors = remapIf(this._stores, store => action in store) | ||
@@ -61,3 +70,3 @@ | ||
this.commit(staged) | ||
this._commit(staged) | ||
} | ||
@@ -64,0 +73,0 @@ |
Sorry, the diff of this file is not supported yet
171213
36
1412