Skip to content

Instantly share code, notes, and snippets.

@FbN
Last active April 28, 2019 16:01
Show Gist options
  • Save FbN/453b6688e21327f0280929626111a726 to your computer and use it in GitHub Desktop.
Save FbN/453b6688e21327f0280929626111a726 to your computer and use it in GitHub Desktop.
mm function
// I: Immutable js library
// M: Most js
// m: Mithril
import { m, I, M } from './vendor.mjs'
export { mm, adapters, route }
// ...
// Function that generate mithril components based on most streams
// initialState: Map of initial state. Streams returned by VM will be matched by name to update this keys values.
// vm: The VM function
// view: The View function
const mm = (initialState, vm, view) => vnode => {
// We make vnode an Immutable record
const VnodeRecord = new I.Record({
tag: undefined,
key: undefined,
attrs: undefined,
children: undefined,
text: undefined,
dom: undefined
})
const StateRecord = new I.Record(initialState || {})
let state = StateRecord()
const [_$done, $done] = multicastAdapter()
// Call the VM
const [triggers, streams] = vm(VnodeRecord(vnode))
// declare lifecycle streams & triggers
const { _$oninit, _$oncreate, _$onupdate, _$onremove } = triggers
const { $oninit, $oncreate, $onupdate, $onremove, ...effects } = streams
// Isolate VM state streams
const stateStreams = (stateKeys, effects) =>
stateKeys.reduce(
(res, key) => res.push(effects['$' + key] || null) && res,
[]
)
// Isolate VM effect streams
const effectStreams = (stateKeys, effects) =>
Object.keys(effects)
.filter(key => !stateKeys.includes(key.substring(1)))
.reduce((res, key) => res.push(effects[key]) && res, [])
// Function that recreate state
const stateObject = stateKeys => (...arrStatus) =>
stateKeys.map((key, index) => [key, index]).reduce((res, entry) => {
res[entry[0]] = arrStatus[entry[1]]
return res
}, {})
// State keys
const stateKeys = Object.keys(initialState)
// return the POJO Mithril Component
return {
oninit: vnode => {
_$app(
M.until(
$done,
M.merge(
M.tap(
m.redraw,
M.merge(
M.tap(newState => {
state = StateRecord(newState)
}, M.combineArray(stateObject(stateKeys), stateStreams(stateKeys, effects))),
M.mergeArray(effectStreams(stateKeys, effects))
)
),
M.mergeArray(
[$oninit, $oncreate, $onupdate, $onremove].filter(
e => e
)
)
)
)
)
_$oninit && _$oninit(vnode)
},
oncreate: vnode => _$oncreate && _$oncreate(VnodeRecord(vnode)),
onupdate: vnode => _$onupdate && _$onupdate(VnodeRecord(vnode)),
onremove: vnode => {
_$onremove && _$onremove(VnodeRecord(vnode))
_$done(true)
},
view: vnode => view(state, triggers, VnodeRecord(vnode))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment