1 | import curry from 'ramda/src/curry'
|
2 |
|
3 | import { createStore, applyMiddleware } from 'redux'
|
4 | import thunk from 'redux-thunk'
|
5 |
|
6 | import diff from 'virtual-dom/diff'
|
7 | import patch from 'virtual-dom/patch'
|
8 | import createElement from 'virtual-dom/create-element'
|
9 | import Delegator from 'dom-delegator'
|
10 |
|
11 | import Map from './Map'
|
12 |
|
13 |
|
14 | const delegator = Delegator()
|
15 | const createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 | export function start (component) {
|
27 | const { init, update, view } = component
|
28 | const [initialState, initialAction] = handleInit(init)
|
29 |
|
30 |
|
31 | let dispatch = x => x
|
32 |
|
33 | const store = createStoreWithMiddleware((state = initialState, action) => {
|
34 | const newState = update(state, action, dispatch)
|
35 |
|
36 | return (typeof newState === 'undefined') ? state : newState
|
37 | })
|
38 |
|
39 | dispatch = action => {
|
40 | return event => {
|
41 | if (event) {
|
42 | action.event = event
|
43 | }
|
44 |
|
45 | store.dispatch(action)
|
46 | }
|
47 | }
|
48 |
|
49 | if (initialAction) {
|
50 | store.dispatch(initialAction)
|
51 | }
|
52 |
|
53 | let tree = view(initialState, dispatch)
|
54 | const rootNode = createElement(tree)
|
55 |
|
56 | store.subscribe(() => {
|
57 | tree = patchTree(
|
58 | rootNode,
|
59 | tree,
|
60 | view(store.getState(), dispatch)
|
61 | )
|
62 | })
|
63 |
|
64 | return rootNode
|
65 | }
|
66 |
|
67 |
|
68 |
|
69 | function patchTree (rootNode, oldTree, newTree) {
|
70 | patch(rootNode, diff(oldTree, newTree))
|
71 |
|
72 | return newTree
|
73 | }
|
74 |
|
75 |
|
76 |
|
77 | export function initializeComponent ({ init }, dispatch) {
|
78 | const [initialState, initialAction] = handleInit(init)
|
79 |
|
80 | if (dispatch && initialAction) {
|
81 | dispatch(initialState)(initialAction)()
|
82 | }
|
83 |
|
84 | return initialState
|
85 | }
|
86 |
|
87 |
|
88 |
|
89 | function handleInit (init) {
|
90 | const _res = init()
|
91 | const res = Array.isArray(_res) ? _res : [_res]
|
92 |
|
93 | return [new Map(res[0]), res[1]]
|
94 | }
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 | export const forwardDispatch = curry((action, dispatch, state) => {
|
102 | return forwardAction => {
|
103 | if (typeof forwardAction === 'function') {
|
104 |
|
105 |
|
106 |
|
107 | return dispatch((rawDispatch) => {
|
108 | const getState = () => state
|
109 | const fwd = forwardDispatch(action, rawDispatch, state)
|
110 |
|
111 | forwardAction(fwd, getState)
|
112 | })
|
113 | }
|
114 |
|
115 |
|
116 | return dispatch(Object.assign({}, action, { __fwdAction: forwardAction }))
|
117 | }
|
118 | })
|