choo: add initial render

This commit is contained in:
Yoshua Wuyts
2016-05-11 13:51:17 +07:00
parent c28d37ac84
commit 48d43eaf09
4 changed files with 161 additions and 6 deletions
+8 -2
View File
@@ -24,10 +24,10 @@ const app = choo()
app.model('title', { app.model('title', {
state: { title: 'my-demo-app' }, state: { title: 'my-demo-app' },
reducers: { reducers: {
'update': (action, state) => ({ title: action.payload }) update: (action, state) => ({ title: action.payload })
}, },
effects: { effects: {
'update': (action, state) => document.title = action.title update: (action, state) => (document.title = action.title)
} }
}) })
@@ -59,6 +59,12 @@ document.appendChild(node)
## API ## API
### choo ### choo
## Packages used
- __views:__ [`yo-yo`](https://github.com/maxogden/yo-yo)
- __models:__ [`send-action`](https://github.com/sethvincent/send-action),
[`xtend`](https://github.com/raynos/xtend)
- __routes:__ [`sheet-router`](https://github.com/yoshuawuyts/sheet-router)
## Installation ## Installation
```sh ```sh
$ npm install choo $ npm install choo
+30
View File
@@ -0,0 +1,30 @@
const choo = require('../')
const app = choo()
app.model('title', {
state: { title: 'my-demo-app' },
reducers: {
'update': (action, state) => ({ title: action.payload })
},
effects: {
'update': (action, state, send) => (document.title = action.title)
}
})
const mainView = (params, state, send) => choo.view`
<main class="app">
<h1>${state.title}</h1>
<label>Set the title</label>
<input
type="text"
placeholder=${state.title}
oninput=${(e) => send('title:update', { payload: e.target.value })}>
</main>
`
app.router((route) => [
route('/', mainView)
])
const node = app.start()
document.body.appendChild(node)
+116 -3
View File
@@ -1,8 +1,121 @@
const assert = require('assert') // const history = require('sheet-router/history')
const sheetRouter = require('sheet-router')
const document = require('global/document')
// const href = require('sheet-router/href')
const sendAction = require('send-action')
const mutate = require('xtend/mutable')
const xtend = require('xtend')
const yo = require('yo-yo')
choo.view = yo
module.exports = choo module.exports = choo
// A framework for creating solid web applications // A framework for creating sturdy web applications
// null -> null // null -> fn
function choo () { function choo () {
var _router = null
var _models = [ appInit() ]
start.router = router
start.model = model
start.start = start
return start
// start the application
// str|DOMNode -> DOMNode
function start (query) {
const events = bootstrap(_models)
const send = sendAction({
onaction: events.middleware,
onchange: onchange,
state: events.state
})
const node = _router(send.state().location, send.state(), send)
console.log(node)
document.body.appendChild(node)
// update on every change
function onchange (action, state) {
const el = document.querySelector('#main')
yo.update(el, router(state.location, send, state))
}
}
// register all routes
// [obj|fn] -> null
function router (cb) {
_router = sheetRouter(cb)
}
// create a new model
// (str?, obj) -> null
function model (name, model) {
if (!model) model = name
if (typeof name === 'string') model.name = name
_models.push(model)
}
}
function appInit () {
return {
state: {
location: document.location.href
},
reducers: {
location: setLocation
}
}
// handle href links
function setLocation (action, state) {
const location = action.location.replace(/#.*/, '')
return xtend(state, { location: location })
}
}
function bootstrap (events) {
const initialState = { }
const reducers = {}
const effects = {}
events.forEach(function (event) {
const name = event.name
if (event.state) mutate(initialState, event.state)
if (event.reducers) {
Object.keys(event.reducers).forEach(function (key) {
if (name) {
reducers[name + ':' + key] = event.reducers[key]
} else {
reducers[key] = event.reducers[key]
}
})
}
if (event.effects) {
Object.keys(event.effects).forEach(function (key) {
if (name) {
effects[name + ':' + key] = event.effects[key]
} else {
effects[key] = event.effects[key]
}
})
}
})
return {
middleware: modifyState,
state: initialState
}
function modifyState (action, state, send) {
if (reducers[action.type]) {
return reducers[action.type](action, state, send)
} else if (effects[action.type]) {
effects[action.type](action, state, send)
return state
} else {
throw new Error('Could not find action ' + action.type)
}
}
} }
+7 -1
View File
@@ -18,7 +18,13 @@
"tiny" "tiny"
], ],
"license": "MIT", "license": "MIT",
"dependencies": {}, "dependencies": {
"global": "^4.3.0",
"send-action": "^1.1.0",
"sheet-router": "^2.0.4",
"xtend": "^4.0.1",
"yo-yo": "^1.2.0"
},
"devDependencies": { "devDependencies": {
"dependency-check": "^2.5.1", "dependency-check": "^2.5.1",
"istanbul": "^0.4.3", "istanbul": "^0.4.3",