armo-breadboard
Version:
Edit a live React component's source in real time.
82 lines (70 loc) • 2.73 kB
JavaScript
import PropTypes from 'prop-types'
import { Controller, instantiateController } from 'react-controllers'
import { noop } from 'armo-util'
import BreadboardBuilder from './BreadboardBuilder'
import ConsoleController from './ConsoleController'
export default class BreadboardController extends Controller {
static propTypes = {
modes: PropTypes.shape({
transformedSource: PropTypes.bool,
browser: PropTypes.bool,
console: PropTypes.bool,
}).isRequired,
sources: PropTypes.shape({
bus: PropTypes.object.isRequired,
model: PropTypes.shape({
value: PropTypes.objectOf(PropTypes.string).isRequired,
onChange: PropTypes.func.isRequired,
}),
}).isRequired,
transforms: PropTypes.arrayOf(PropTypes.array).isRequired,
// TODO: if we have transformedSource but not browser/console, only
// transform appropriate source
selected: PropTypes.object,
}
static actions = {
}
constructor(props) {
super(props)
const transformedSources = this.setTransformsAndBuild(props.transforms, props.sources.model.value)
this.state = {
transformedSources: transformedSources,
sourcesChangedSinceLastBuild: false,
firstTransformError: findFirstError(transformedSources),
consoleController: instantiateController(ConsoleController),
}
}
controllerWillReceiveProps(nextProps) {
const nextModes = nextProps.modes
const nextModeRequiresBuild = nextModes.browser || nextModes.console || nextModes.transformedSource
const sourcesDidChange = nextProps.sources !== this.props.sources
let rebuild = false
if (nextProps.transforms !== this.props.transforms) {
const transformedSources = this.setTransformsAndBuild(nextProps.transforms, nextProps.sources.model.value)
this.setState({
transformedSources: transformedSources,
firstTransformError: findFirstError(transformedSources),
})
}
else if (nextModeRequiresBuild && sourcesDidChange || this.state.sourcesChangedSinceLastBuild) {
const transformedSources = this.builder.buildAll(nextProps.sources.model.value)
this.setState({
transformedSources: transformedSources,
sourcesChangedSinceLastBuild: false,
firstTransformError: findFirstError(transformedSources),
})
}
else if (sourcesDidChange && !this.state.sourcesChangedSinceLastBuild) {
this.setState({
sourcesChangedSinceLastBuild: true,
})
}
}
setTransformsAndBuild(transforms, sources) {
this.builder = new BreadboardBuilder(transforms)
return this.builder.buildAll(sources)
}
}
function findFirstError(obj) {
return Object.values(obj).find(x => x instanceof Error)
}