-
-
Save AlexGalays/f3ee01ff940defd147700c2725dd3976 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React = __React; | |
import { State, StateMap } from './abyssa'; | |
export interface ReactState { | |
(uri: string, component: React.ComponentClass<any> | React.StatelessComponent<any>, children?: StateMap): State; | |
} | |
export default function reactStateForContainer(container: HTMLElement): ReactState; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Addon making using React easier */ | |
import _React from 'react'; | |
import _ReactDOM from 'react-dom'; | |
export default (function() { | |
// Enable this addon even in build-less systems (JsFiddle, etc) | |
const React = _React || window.React; | |
const ReactDOM = _ReactDOM || window.ReactDOM; | |
function createEl(fromClass, route, params, acc, key, child) { | |
return React.createElement(fromClass, { route, params, acc, key }, child); | |
} | |
function parentStates(stateApi) { | |
const result = []; | |
let parent = stateApi.parent; | |
while (parent) { | |
result.push(parent); | |
parent = parent.parent; | |
} | |
return result; | |
} | |
// Enable this addon even in build-less systems (JsFiddle, etc) | |
if (window.Abyssa) | |
window.Abyssa.ReactState = ReactStateForContainer | |
return function ReactStateForContainer(container) { | |
let stateId = 0; | |
const componentByState = {}; | |
return function ReactState(uri, component, children) { | |
// Create the Abyssa state object | |
const state = { | |
data: { id: stateId++ }, | |
uri, | |
children | |
}; | |
componentByState[state.data.id] = component; | |
// The router will add a default state to any parent without one; Add ours first so that it's a ReactState. | |
if (children && !Object.keys(children).some(name => children[name].uri.split('?')[0] == '')) | |
children._default_ = ReactState(''); | |
state.enter = function(params, acc, router) { | |
const route = router.current(); | |
// Let the component react to the route change, e.g to redirect to another state | |
if (component && component.onEnter) { | |
const current = route.fullName; | |
component.onEnter(); | |
// The current state changed, cancel everything. | |
if (router.current().fullName != current) return; | |
} | |
// It is the responsability of the leaf state to render the whole component hierarchy; Bail if we're a parent. | |
if (children) return; | |
const stateApi = router.findState(state); | |
const parents = parentStates(stateApi); | |
const states = component ? [stateApi].concat(parents) : parents; | |
// The actual VDOM element created from the component class hierarchy | |
const instance = states.slice(1).reduce((child, parent) => { | |
const parentComp = componentByState[parent.data.id] | |
return createEl(parentComp, route, params, acc, parent.fullName, child); | |
}, createEl(componentByState[states[0].data.id], route, params, acc, states[0].fullName)); | |
ReactDOM.render(instance, container); | |
}; | |
return state; | |
} | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment