Skip to content

Instantly share code, notes, and snippets.

@mnichols
Last active December 29, 2016 06:31
Show Gist options
  • Save mnichols/d221031de888e9d24ddc48defc6497ff to your computer and use it in GitHub Desktop.
Save mnichols/d221031de888e9d24ddc48defc6497ff to your computer and use it in GitHub Desktop.
import objectPath from "object-path"
function assertValue(funcName, value) {
if(typeof value !== 'undefined') {
return
}
throw new Error(`You are returning 'undefined' from ${funcName}. This is a bug.`)
}
/**
* nestComponent
*
* @param path - the node/property where the component should mount onto the state tree
* @returns {Object} pathed component spec, write to and reading from `path` where appropriate
*/
export default function nestComponent(path) {
return function inner(component) {
let topLevel = {}
function V(props = {}, actions) {
if(!component.view) {
topLevel = {}
return null
}
const namespaced = objectPath.get(topLevel, path, {})
if(props.children) {
namespaced.children = props.children
}
const result = component.view({ ...namespaced, ...props }, actions)
//reset
topLevel = {}
return result
}
const result = {
initialModel: component.initialModel ? ({ model }) => {
let result = component.initialModel({})
objectPath.set(model, path, Object.assign(objectPath.get(model, path, {}), result));
return model;
} : null,
receive: component.receive ? ({ model, proposal }) => {
let result = component.receive({ model: objectPath.get(model, path, {}), proposal })
assertValue('receive', result)
objectPath.set(model, path, result)
return topLevel = model
} : null,
view: V,
actions: component.actions,
postRender: component.postRender ? ({ model, state }) => component.postRender({ model: objectPath.get(model, path, {}), state: objectPath.get(state, path, {}) }) : null,
ready: component.ready,
nextAction: component.nextAction ? ({ model, proposal, actions, propose }) => component.nextAction({ model: objectPath.get(model, path, {}), proposal, actions, propose }) : null,
state: component.state ? ({ model, state }) => {
let result = component.state({ model: objectPath.get(model, path, {}), state: objectPath.get(state, path, {}) })
assertValue('state', result)
//dont mutate app model
topLevel = { ...model }
objectPath.set(topLevel, path, result)
return topLevel
} : ({ model }) => topLevel = model,
}
return result
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment