1 | import { Component } from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 |
|
4 | var isShallowEqual = function isShallowEqual (a, b) {
|
5 | if (a === b) { return true }
|
6 | for (var i in a) { if (!(i in b)) { return false } }
|
7 | for (var i in b) { if (a[i] !== b[i]) { return false } }
|
8 | return true
|
9 | };
|
10 |
|
11 | var isObjectNotNull = function (a, b) {
|
12 | return (
|
13 | typeof a === 'object' && typeof b === 'object' && a !== null && b !== null
|
14 | )
|
15 | };
|
16 |
|
17 | var State = (function (Component$$1) {
|
18 | function State (props, context) {
|
19 | Component$$1.call(this, props, context);
|
20 | this.broadcast = context.__statty__.broadcast;
|
21 | this.inspect = context.__statty__.inspect;
|
22 | this.state = props.state
|
23 | ? props.state
|
24 | : props.select(this.broadcast.getState());
|
25 | this.update = this.update.bind(this);
|
26 | this.setStateIfNeeded = this.setStateIfNeeded.bind(this);
|
27 | }
|
28 |
|
29 | if ( Component$$1 ) State.__proto__ = Component$$1;
|
30 | State.prototype = Object.create( Component$$1 && Component$$1.prototype );
|
31 | State.prototype.constructor = State;
|
32 |
|
33 | State.prototype.update = function update (updaterFn) {
|
34 | if (this.props.state) {
|
35 | this.setState(updaterFn);
|
36 | } else {
|
37 | var oldState = this.broadcast.getState();
|
38 | var nextState = updaterFn(oldState);
|
39 | this.inspect && this.inspect(oldState, nextState, updaterFn);
|
40 | this.broadcast.setState(nextState);
|
41 | }
|
42 | };
|
43 |
|
44 | State.prototype.setStateIfNeeded = function setStateIfNeeded (nextState) {
|
45 | var oldSelectdedState = this.state;
|
46 | var newSelectedState = this.props.select(nextState);
|
47 | if (
|
48 | !isObjectNotNull(oldSelectdedState, newSelectedState) ||
|
49 | !isShallowEqual(oldSelectdedState, newSelectedState)
|
50 | ) {
|
51 | this.setState(newSelectedState);
|
52 | }
|
53 | };
|
54 |
|
55 | State.prototype.componentDidMount = function componentDidMount () {
|
56 | if (!this.props.state) {
|
57 | this.subscriptionId = this.broadcast.subscribe(this.setStateIfNeeded);
|
58 |
|
59 |
|
60 | this.setStateIfNeeded(this.broadcast.getState());
|
61 | }
|
62 | };
|
63 |
|
64 | State.prototype.componentWillUnmount = function componentWillUnmount () {
|
65 | this.subscriptionId && this.broadcast.unsubscribe(this.subscriptionId);
|
66 | };
|
67 |
|
68 | State.prototype.render = function render () {
|
69 | return (
|
70 | this.props.render(
|
71 | this.props.select(
|
72 | this.props.state ? this.state : this.broadcast.getState()
|
73 | ),
|
74 | this.update
|
75 | ) || null
|
76 | )
|
77 | };
|
78 |
|
79 | return State;
|
80 | }(Component));
|
81 |
|
82 | State.defaultProps = {
|
83 | select: function (s) { return s; },
|
84 | render: function () { return null; }
|
85 | };
|
86 |
|
87 | State.contextTypes = {
|
88 | __statty__: PropTypes.object.isRequired
|
89 | };
|
90 |
|
91 | State.propTypes = {
|
92 | state: PropTypes.object,
|
93 | render: PropTypes.func,
|
94 | select: PropTypes.func
|
95 | };
|
96 |
|
97 | function createBroadcast (initialState) {
|
98 | var listeners = {};
|
99 | var id = 1;
|
100 | var _state = initialState;
|
101 |
|
102 | function getState () {
|
103 | return _state
|
104 | }
|
105 |
|
106 | function setState (state) {
|
107 | _state = state;
|
108 | var keys = Object.keys(listeners);
|
109 | var i = 0;
|
110 | var len = keys.length;
|
111 | for (; i < len; i++) {
|
112 |
|
113 | if (listeners[keys[i]]) { listeners[keys[i]](state); }
|
114 | }
|
115 | }
|
116 |
|
117 |
|
118 | function subscribe (listener) {
|
119 | if (typeof listener !== 'function') {
|
120 | throw new Error('listener must be a function.')
|
121 | }
|
122 | var currentId = id;
|
123 | listeners[currentId] = listener;
|
124 | id += 1;
|
125 | return currentId
|
126 | }
|
127 |
|
128 |
|
129 | function unsubscribe (id) {
|
130 | listeners[id] = undefined;
|
131 | }
|
132 |
|
133 | return { getState: getState, setState: setState, subscribe: subscribe, unsubscribe: unsubscribe }
|
134 | }
|
135 |
|
136 | var Provider = (function (Component$$1) {
|
137 | function Provider (props, context) {
|
138 | Component$$1.call(this, props, context);
|
139 | this.broadcast = createBroadcast(props.state);
|
140 | }
|
141 |
|
142 | if ( Component$$1 ) Provider.__proto__ = Component$$1;
|
143 | Provider.prototype = Object.create( Component$$1 && Component$$1.prototype );
|
144 | Provider.prototype.constructor = Provider;
|
145 |
|
146 | Provider.prototype.getChildContext = function getChildContext () {
|
147 | return {
|
148 | __statty__: {
|
149 | broadcast: this.broadcast,
|
150 | inspect: this.props.inspect
|
151 | }
|
152 | }
|
153 | };
|
154 |
|
155 | Provider.prototype.render = function render () {
|
156 | var children = this.props.children;
|
157 | return Array.isArray(children) ? children[0] : children
|
158 | };
|
159 |
|
160 | return Provider;
|
161 | }(Component));
|
162 |
|
163 | Provider.childContextTypes = {
|
164 | __statty__: PropTypes.object
|
165 | };
|
166 |
|
167 | Provider.propTypes = {
|
168 | inspect: PropTypes.func,
|
169 | state: PropTypes.object.isRequired,
|
170 | children: PropTypes.node.isRequired
|
171 | };
|
172 |
|
173 | export { Provider, State };
|