refactor: type renderers
This commit is contained in:
parent
3f1a94545b
commit
c84caf601e
|
@ -1,16 +0,0 @@
|
|||
import Actions from './actions';
|
||||
import Bool from './bool';
|
||||
import Condition from './condition';
|
||||
import Number from './number';
|
||||
import String from './string';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function propertyComponents() {
|
||||
return {
|
||||
actions: Actions,
|
||||
bool: Bool,
|
||||
condition: Condition,
|
||||
number: Number,
|
||||
string: String,
|
||||
};
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import {compose, mapObject} from '@avocado/core';
|
||||
import {all} from '@avocado/entity/trait/trait-components.scwp';
|
||||
import {all as allTraitComponents} from '@avocado/entity/trait/trait-components.scwp';
|
||||
import {lookupTrait} from '@avocado/entity';
|
||||
import contempo from 'contempo';
|
||||
import {produce} from 'immer';
|
||||
|
@ -15,6 +15,8 @@ import {
|
|||
import {createSelector} from '@reduxjs/toolkit';
|
||||
import {deregisterHooks, invokeHookFlat, registerHooks} from 'scwp';
|
||||
|
||||
import {all as allTypeRenderers} from './types/type-renderers.scwp';
|
||||
|
||||
const SCROLL_MAG = 80;
|
||||
|
||||
const decorate = compose(
|
||||
|
@ -35,24 +37,26 @@ const decorate = compose(
|
|||
let TraitComponents;
|
||||
const ensureTraitComponents = () => {
|
||||
if (!TraitComponents) {
|
||||
TraitComponents = Object.values(all()).reduce((r, M) => {
|
||||
TraitComponents = Object.values(allTraitComponents()).reduce((r, M) => {
|
||||
const {default: TraitComponent} = M;
|
||||
return {...r, [TraitComponent.type]: TraitComponent};
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
let PropertyComponents;
|
||||
const ensurePropertyComponents = () => {
|
||||
if (!PropertyComponents) {
|
||||
const results = invokeHookFlat('propertyComponents');
|
||||
PropertyComponents = results.reduce((r, map) => ({...r, ...map}), {});
|
||||
let TypeRenderers;
|
||||
const ensureTypeRenderers = () => {
|
||||
if (!TypeRenderers) {
|
||||
TypeRenderers = Object.values(allTypeRenderers()).reduce((r, M) => {
|
||||
const {default: {type, component}} = M;
|
||||
return {...r, [type]: component};
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
|
||||
const makeTabSelector = (type) => createSelector(
|
||||
(_) => _,
|
||||
(trait) => {
|
||||
ensurePropertyComponents();
|
||||
ensureTypeRenderers();
|
||||
ensureTraitComponents();
|
||||
const {params: paramsRaw, state: stateRaw} = trait;
|
||||
const {[type]: TraitComponent} = TraitComponents;
|
||||
|
@ -65,9 +69,15 @@ const makeTabSelector = (type) => createSelector(
|
|||
// eslint-disable-next-line no-shadow
|
||||
Object.values(mapObject(description, (description, key) => {
|
||||
const {label, options, type: componentType} = description;
|
||||
const Component = PropertyComponents[componentType];
|
||||
const Component = TypeRenderers[componentType];
|
||||
return Component
|
||||
? (
|
||||
<label>
|
||||
<span className="text">
|
||||
{label}
|
||||
:
|
||||
</span>
|
||||
<div className="invisible-separator" />
|
||||
<Component
|
||||
key={key}
|
||||
label={label}
|
||||
|
@ -75,6 +85,7 @@ const makeTabSelector = (type) => createSelector(
|
|||
options={options}
|
||||
value={values[key]}
|
||||
/>
|
||||
</label>
|
||||
)
|
||||
: null;
|
||||
}))
|
||||
|
|
41
src/client/components/types/actions.type-renderer.jsx
Normal file
41
src/client/components/types/actions.type-renderer.jsx
Normal file
|
@ -0,0 +1,41 @@
|
|||
import {compose} from '@avocado/core';
|
||||
import classnames from 'classnames';
|
||||
import contempo from 'contempo';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import propertyPropTypes from './property-prop-types';
|
||||
import Value from './value.type-renderer';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./actions.raw.scss')),
|
||||
);
|
||||
|
||||
const Actions = ({
|
||||
name,
|
||||
label,
|
||||
options,
|
||||
value,
|
||||
}) => (
|
||||
<div className="actions">
|
||||
<ol>
|
||||
{
|
||||
value.traversals.length > 0 && (
|
||||
value.traversals.map(
|
||||
(traversal) => <li><Value.component value={traversal} /></li>,
|
||||
)
|
||||
)
|
||||
}
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
|
||||
Actions.propTypes = {
|
||||
...propertyPropTypes,
|
||||
value: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
export default {
|
||||
type: 'actions',
|
||||
component: decorate(Actions),
|
||||
};
|
|
@ -8,14 +8,7 @@ const Bool = ({
|
|||
label,
|
||||
value,
|
||||
}) => (
|
||||
<label>
|
||||
<span className="text">
|
||||
{label}
|
||||
:
|
||||
</span>
|
||||
<div className="invisible-separator" />
|
||||
<input name={name} type="checkbox" checked={value} />
|
||||
</label>
|
||||
);
|
||||
|
||||
Bool.propTypes = {
|
||||
|
@ -23,4 +16,7 @@ Bool.propTypes = {
|
|||
value: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default Bool;
|
||||
export default {
|
||||
type: 'bool',
|
||||
component: Bool,
|
||||
};
|
|
@ -49,13 +49,7 @@ const Condition = ({
|
|||
options,
|
||||
value,
|
||||
}) => (
|
||||
<label>
|
||||
<span className="text">
|
||||
{label}
|
||||
:
|
||||
</span>
|
||||
<div className="invisible-separator" />
|
||||
<div className="condition">
|
||||
<span className="condition">
|
||||
{
|
||||
value.operands.length > 0 && (() => {
|
||||
switch (value.operator) {
|
||||
|
@ -82,8 +76,7 @@ const Condition = ({
|
|||
}
|
||||
})()
|
||||
}
|
||||
</div>
|
||||
</label>
|
||||
</span>
|
||||
);
|
||||
|
||||
Condition.propTypes = {
|
||||
|
@ -91,4 +84,7 @@ Condition.propTypes = {
|
|||
value: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
export default decorate(Condition);
|
||||
export default {
|
||||
type: 'condition',
|
||||
component: decorate(Condition),
|
||||
};
|
|
@ -9,12 +9,7 @@ const Number = ({
|
|||
options,
|
||||
value,
|
||||
}) => (
|
||||
<label>
|
||||
<span className="text">
|
||||
{label}
|
||||
:
|
||||
</span>
|
||||
<div className="invisible-separator" />
|
||||
<span className="number">
|
||||
{
|
||||
options
|
||||
? (
|
||||
|
@ -26,7 +21,7 @@ const Number = ({
|
|||
)
|
||||
: <input name={name} type="text" value={value} />
|
||||
}
|
||||
</label>
|
||||
</span>
|
||||
);
|
||||
|
||||
Number.propTypes = {
|
||||
|
@ -34,4 +29,7 @@ Number.propTypes = {
|
|||
value: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default Number;
|
||||
export default {
|
||||
type: 'number',
|
||||
component: Number,
|
||||
};
|
|
@ -9,12 +9,7 @@ const String = ({
|
|||
options,
|
||||
value,
|
||||
}) => (
|
||||
<label>
|
||||
<span className="text">
|
||||
{label}
|
||||
:
|
||||
</span>
|
||||
<div className="invisible-separator" />
|
||||
<span className="string">
|
||||
{
|
||||
options
|
||||
? (
|
||||
|
@ -26,7 +21,7 @@ const String = ({
|
|||
)
|
||||
: <input name={name} type="text" value={value} />
|
||||
}
|
||||
</label>
|
||||
</span>
|
||||
);
|
||||
|
||||
String.propTypes = {
|
||||
|
@ -34,4 +29,7 @@ String.propTypes = {
|
|||
value: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default String;
|
||||
export default {
|
||||
type: 'string',
|
||||
component: String,
|
||||
};
|
9
src/client/components/types/type-renderers.scwp.js
Normal file
9
src/client/components/types/type-renderers.scwp.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
function types(scwp) {
|
||||
scwp.enterSelf();
|
||||
scwp.loadSelf('scwp/autoreg', {
|
||||
paths: scwp.paths,
|
||||
root: scwp.root,
|
||||
type: 'type-renderer',
|
||||
});
|
||||
}
|
||||
module.exports = types;
|
0
src/client/components/types/value.raw.scss
Normal file
0
src/client/components/types/value.raw.scss
Normal file
|
@ -13,7 +13,7 @@ const reduceStep = (r, step) => {
|
|||
case 'invoke':
|
||||
return (
|
||||
<span className="step">
|
||||
<span className="invocation"><input value={r} /></span>
|
||||
<span className="fn"><input value={r} /></span>
|
||||
<span className="paren open">(</span>
|
||||
<div className="args">
|
||||
{
|
||||
|
@ -22,22 +22,12 @@ const reduceStep = (r, step) => {
|
|||
(r2, element, i) => (
|
||||
<>
|
||||
{r2}
|
||||
<div
|
||||
className={classnames(
|
||||
'arg',
|
||||
step.args[i + 1].type,
|
||||
)}
|
||||
>
|
||||
<div className={classnames('arg', step.args[i + 1].type)}>
|
||||
{element}
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
<div
|
||||
className={classnames(
|
||||
'arg',
|
||||
step.args[0].type,
|
||||
)}
|
||||
>
|
||||
<div className={classnames('arg', step.args[0].type)}>
|
||||
{renderValue(step.args[0])}
|
||||
</div>,
|
||||
)
|
||||
|
@ -76,7 +66,6 @@ const renderValue = (value) => {
|
|||
return <span className="wrapper"><input value={value.value} /></span>;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className="object">
|
||||
<span className="bracket open">{'{'}</span>
|
||||
<pre contentEditable>
|
||||
|
@ -87,45 +76,29 @@ const renderValue = (value) => {
|
|||
</pre>
|
||||
<span className="bracket close">{'}'}</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./actions.raw.scss')),
|
||||
contempo(require('./value.raw.scss')),
|
||||
);
|
||||
|
||||
const Actions = ({
|
||||
const Value = ({
|
||||
name,
|
||||
label,
|
||||
options,
|
||||
value,
|
||||
}) => (
|
||||
<label>
|
||||
<span className="text">
|
||||
{label}
|
||||
:
|
||||
</span>
|
||||
<div className="invisible-separator" />
|
||||
<div className="actions">
|
||||
<ol>
|
||||
{
|
||||
value.traversals.length > 0 && (
|
||||
value.traversals.map(renderValue).map((o) => <li>{o}</li>)
|
||||
)
|
||||
}
|
||||
</ol>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
}) => renderValue(value);
|
||||
|
||||
Actions.propTypes = {
|
||||
Value.propTypes = {
|
||||
...propertyPropTypes,
|
||||
value: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
export default decorate(Actions);
|
||||
export default {
|
||||
type: 'value',
|
||||
component: decorate(Value),
|
||||
};
|
Loading…
Reference in New Issue
Block a user