refactor: arg options normalization

This commit is contained in:
cha0s 2020-06-23 22:08:23 -05:00
parent 009b298fdb
commit c793b70638
3 changed files with 69 additions and 35 deletions

View File

@ -1,5 +1,5 @@
import {makeCompilable, description as typeDescription} from '@avocado/behavior';
import {compose} from '@avocado/core';
import {compose, mapObject} from '@avocado/core';
import contempo from 'contempo';
import React from 'react';
@ -70,41 +70,46 @@ const Expression = (props) => {
}
case 'invoke': {
const description = descriptionFromOps(context, ops.slice(0, i + 1));
const argTypes = (description.args || []).map(([, {type: argType}]) => argType);
const args = description.args || [];
const argSpecs = Object.values(args).map(([, argSpec]) => argSpec);
return (
<div className="invoke">
<span className="paren open">(</span>
{op.args.map((arg, j) => (
// eslint-disable-next-line react/no-array-index-key
<div className="arg" key={j}>
<label>
{arg.label}
<Value.Component
context={context}
onChange={(argValue, event) => (
onChange({
type: 'expression',
ops: [
...ops.slice(0, i),
{
...ops[i],
args: [
...ops[i].args.slice(0, j),
makeCompilable(argValue),
...ops[i].args.slice(j + 1),
],
},
...ops.slice(i + 1),
],
assign,
}, event)
)}
type={argTypes[j] || 'any'}
value={arg}
/>
</label>
</div>
))}
{op.args.map((arg, j) => {
const argSpec = argSpecs[j] || {type: 'any'};
return (
// eslint-disable-next-line react/no-array-index-key
<div className="arg" key={j}>
<label>
{arg.label}
<Value.Component
context={context}
onChange={(argValue, event) => (
onChange({
type: 'expression',
ops: [
...ops.slice(0, i),
{
...ops[i],
args: [
...ops[i].args.slice(0, j),
makeCompilable(argValue),
...ops[i].args.slice(j + 1),
],
},
...ops.slice(i + 1),
],
assign,
}, event)
)}
options={argSpec.options}
type={argSpec.type || 'any'}
value={arg}
/>
</label>
</div>
);
})}
<span className="paren close">)</span>
</div>
);

View File

@ -15,6 +15,7 @@ const decorate = compose(
const Literal = ({
context,
onChange = () => {},
options: componentOptions,
type,
value: {value},
}) => {
@ -42,7 +43,18 @@ const Literal = ({
.map((option) => <option key={option}>{option}</option>)
}
</select>
{Component ? <Component onChange={onChange} type={actualType} value={value} /> : null}
{
Component
? (
<Component
onChange={onChange}
options={componentOptions}
type={actualType}
value={value}
/>
)
: null
}
</div>
);
};

View File

@ -10,20 +10,37 @@ export function descriptionFromOps(context, ops) {
if (0 === ops.length) {
return description;
}
let previous;
let variable;
for (let i = 0; i < ops.length; ++i) {
if ('invoke' === ops[i].type) {
// eslint-disable-next-line no-continue
continue;
}
const {children} = description;
const {key} = ops[i];
const evaluate = compile({type: 'expression', ops: ops.slice(0, i + 1)});
previous = variable;
variable = evaluate(context);
if ('function' === typeof variable && children[key] && children[key].args) {
const {type} = children[key];
// eslint-disable-next-line no-loop-func
const args = children[key].args.map(([type, spec]) => [
type,
// eslint-disable-next-line no-nested-ternary
spec.options
? {
...spec,
options: ('function' === typeof spec.options ? spec.options(previous) : spec.options),
}
: spec,
]);
description = {
...typeDescription(type),
...children[key],
...{
...children[key],
args,
},
};
}
else {