UNPKG

@skele/classic

Version:

Skele is an architectural framework that assists with building data-driven apps with React or React Native.

128 lines (99 loc) 2.9 kB
'use strict' import * as R from 'ramda' import { Iterable } from 'immutable' import React from 'react' import invariant from 'invariant' import { registry, data, log } from '@skele/core' import ElementView from './ElementView' import { isSubclassOf } from '../impl/classes' const { Registry, chainRegistries, memoize } = registry const { warning } = log const registryAttribute = '@@skele/_uiRegistry' // required subsystems import * as SubSystem from '../subsystem' SubSystem.extend(() => { const registry = new Registry() return { ui: { [registryAttribute]: registry, register(kind, Component) { invariant( data.isElementRef(kind), 'You must provide a valid element reference to register' ) invariant( Component != null && (isSubclassOf(Component, React.Component) || typeof Component === 'function'), 'You must provide a react component class or a pure-function component' ) registry.register(kind, ElementView(kind, Component)) }, reset() { // do nothing as the o // registry.reset() }, }, } }) export default SubSystem.create(system => { const runtime = { registry: getCombinedRegistry(system.subsystemSequence), system, uiFor(element, reactKey = undefined) { return system.subsystems.ui.uiFor(element, reactKey) }, } const _forElement = forElement(runtime) const _forElements = forElements(_forElement) return { name: 'ui', uiFor(element, reactKey = undefined) { if (Iterable.isIndexed(element)) { const ui = _forElements(element) return ui } return _forElement(element, reactKey) }, } }) const forElement = runtime => { const { registry } = runtime const componentFor = memoize(kind => { const C = registry.get(kind) if (C != null) return C(runtime) warning( `Couldn't find the following kind(s) within the registry: [${data.canonical( kind )}]` ) return null }) return (element, reactKey = undefined) => { if (element == null) { return null } invariant( data.isElement(element), 'You provided something other than an element for ui lookup' ) invariant( element._keyPath != null, 'The current implementation requires a Cursor to be passed in. This may be removed in the future' ) const kind = data.kindOf(element) const Component = componentFor(kind) if (Component) { return <Component element={element} key={reactKey} /> } } } const forElements = R.curry((elementBuilder, elementSeq) => elementSeq.map(elementBuilder).filter(ui => !!ui) ) const getRegistry = R.path(['ui', registryAttribute]) const getCombinedRegistry = R.pipe( R.map(getRegistry), R.reject(R.isNil), chainRegistries )