flow: expressions
This commit is contained in:
parent
7a0915cd56
commit
234421b674
|
@ -38,6 +38,7 @@
|
|||
"html-entities": "1.3.1",
|
||||
"immer": "^7.0.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.memoize": "^4.1.2",
|
||||
"memorystore": "^1.6.2",
|
||||
"normalizr": "^3.6.0",
|
||||
"prop-types": "^15",
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
text-align-last: center;
|
||||
}
|
||||
|
||||
.operand .traversal {
|
||||
.operand .expression {
|
||||
display: flex;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {makeCompilable} from '@avocado/behavior';
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
import PropTypes from 'prop-types';
|
||||
|
@ -6,7 +7,6 @@ import React, {useRef} from 'react';
|
|||
import Value from '~/client/value';
|
||||
|
||||
import propTypes from './prop-types';
|
||||
import {toBehaviorItem} from './typing';
|
||||
|
||||
const binaryOps = [
|
||||
['is', 'is equal to'],
|
||||
|
@ -36,7 +36,7 @@ const Condition = ({
|
|||
const {operands} = value;
|
||||
const mergeToOperand = (index, operandValue) => [
|
||||
...operands.slice(0, index),
|
||||
toBehaviorItem(operandValue),
|
||||
makeCompilable(operandValue),
|
||||
...operands.slice(index + 1),
|
||||
];
|
||||
const makeOnChange = (index) => (newValue, event) => {
|
||||
|
@ -44,6 +44,7 @@ const Condition = ({
|
|||
operatorRef.current === event.target
|
||||
? {operator: newValue}
|
||||
: {operands: mergeToOperand(index, newValue)},
|
||||
event,
|
||||
);
|
||||
};
|
||||
return (
|
||||
|
|
|
@ -34,10 +34,10 @@
|
|||
}
|
||||
|
||||
.arg label {
|
||||
padding: 0.5em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.arg .traversal {
|
||||
.arg .expression {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
@ -58,5 +58,5 @@
|
|||
|
||||
.op {
|
||||
align-self: flex-start;
|
||||
margin: 0.5em 1em;
|
||||
margin: 0.125em;
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import {makeCompilable} from '@avocado/behavior';
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
import React from 'react';
|
||||
|
@ -6,15 +7,13 @@ import Value from '~/client/value';
|
|||
|
||||
import propTypes from './prop-types';
|
||||
import {
|
||||
defaultSteps,
|
||||
descriptionFromSteps,
|
||||
stepsOptions,
|
||||
toBehaviorItem,
|
||||
typeFromSteps,
|
||||
defaultOps,
|
||||
descriptionFromOps,
|
||||
opsOptions,
|
||||
} from './typing';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./traversal.raw.scss')),
|
||||
contempo(require('./expression.raw.scss')),
|
||||
);
|
||||
|
||||
const Traversal = (props) => {
|
||||
|
@ -24,37 +23,36 @@ const Traversal = (props) => {
|
|||
type,
|
||||
value = {},
|
||||
} = props;
|
||||
const {steps, value: assignValue} = value;
|
||||
const stepsType = type || typeFromSteps(context, steps);
|
||||
const optionsList = stepsOptions(context, steps, stepsType);
|
||||
const {ops, assign} = value;
|
||||
const optionsList = opsOptions(context, ops, type);
|
||||
return (
|
||||
<div className="traversal">
|
||||
{steps.map((step, i) => (
|
||||
<div className="expression">
|
||||
{ops.map((op, i) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<span className="step" key={i}>
|
||||
<span className="op" key={i}>
|
||||
{
|
||||
(() => {
|
||||
switch (step.type) {
|
||||
switch (op.type) {
|
||||
case 'key': {
|
||||
const options = optionsList[i];
|
||||
return (
|
||||
<span className="key" data-step-key={step.key}>
|
||||
<span className="key" data-op-key={op.key}>
|
||||
<select
|
||||
onChange={(event) => {
|
||||
const newSteps = [
|
||||
...steps.slice(0, i),
|
||||
...ops.slice(0, i),
|
||||
{
|
||||
...steps[i],
|
||||
...ops[i],
|
||||
key: event.target.value,
|
||||
},
|
||||
];
|
||||
return onChange({
|
||||
...value,
|
||||
steps: defaultSteps(context, stepsType, newSteps),
|
||||
ops: defaultOps(context, type, newSteps),
|
||||
value: undefined,
|
||||
});
|
||||
}, event);
|
||||
}}
|
||||
value={step.key}
|
||||
value={op.key}
|
||||
>
|
||||
{
|
||||
options
|
||||
|
@ -66,12 +64,12 @@ const Traversal = (props) => {
|
|||
);
|
||||
}
|
||||
case 'invoke': {
|
||||
const description = descriptionFromSteps(context, steps);
|
||||
const description = descriptionFromOps(context, ops.slice(0, i + 1));
|
||||
const argTypes = (description.args || []).map(([, {type: argType}]) => argType);
|
||||
return (
|
||||
<div className="invoke">
|
||||
<span className="paren open">(</span>
|
||||
{step.args.map((arg, j) => (
|
||||
{op.args.map((arg, j) => (
|
||||
<div className="arg" key={JSON.stringify(arg)}>
|
||||
<label>
|
||||
{arg.label}
|
||||
|
@ -79,20 +77,20 @@ const Traversal = (props) => {
|
|||
context={context}
|
||||
onChange={(argValue, event) => (
|
||||
onChange({
|
||||
type: 'traversal',
|
||||
steps: [
|
||||
...steps.slice(0, i),
|
||||
type: 'expression',
|
||||
ops: [
|
||||
...ops.slice(0, i),
|
||||
{
|
||||
...steps[i],
|
||||
...ops[i],
|
||||
args: [
|
||||
...steps[i].args.slice(0, j),
|
||||
toBehaviorItem(argValue),
|
||||
...steps[i].args.slice(j + 1),
|
||||
...ops[i].args.slice(0, j),
|
||||
makeCompilable(argValue),
|
||||
...ops[i].args.slice(j + 1),
|
||||
],
|
||||
},
|
||||
...steps.slice(i + 1),
|
||||
...ops.slice(i + 1),
|
||||
],
|
||||
value: assignValue,
|
||||
assign,
|
||||
}, event)
|
||||
)}
|
||||
type={argTypes[j] || 'any'}
|
||||
|
@ -113,20 +111,20 @@ const Traversal = (props) => {
|
|||
</span>
|
||||
))}
|
||||
{
|
||||
assignValue && (
|
||||
assign && (
|
||||
<span className="assign">
|
||||
<span className="op">=</span>
|
||||
<Value.Component
|
||||
context={context}
|
||||
onChange={(valueValue, event) => (
|
||||
onChange({
|
||||
type: 'traversal',
|
||||
steps,
|
||||
value: toBehaviorItem(valueValue),
|
||||
type: 'expression',
|
||||
ops,
|
||||
value: makeCompilable(valueValue),
|
||||
}, event)
|
||||
)}
|
||||
type={typeFromSteps(context, steps)}
|
||||
value={assignValue}
|
||||
type={type}
|
||||
value={assign}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
|
@ -140,6 +138,6 @@ Traversal.propTypes = {
|
|||
};
|
||||
|
||||
export default {
|
||||
type: 'traversal',
|
||||
type: 'expression',
|
||||
Component: decorate(Traversal),
|
||||
};
|
|
@ -4,44 +4,44 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
|
||||
import propTypes from './prop-types';
|
||||
import Traversal from './traversal.type-renderer';
|
||||
import Expression from './expression.type-renderer';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./actions.raw.scss')),
|
||||
contempo(require('./expressions.raw.scss')),
|
||||
);
|
||||
|
||||
const Actions = ({
|
||||
const Expressions = ({
|
||||
context,
|
||||
onChange = () => {},
|
||||
value = {},
|
||||
}) => {
|
||||
const {traversals = []} = value;
|
||||
const {expressions = []} = value;
|
||||
return (
|
||||
<div className="actions">
|
||||
<div className="expressions">
|
||||
<ol>
|
||||
{
|
||||
traversals.length > 0 && (
|
||||
traversals.map(
|
||||
(traversal, i) => (
|
||||
expressions.length > 0 && (
|
||||
expressions.map(
|
||||
(expression, i) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<li key={i}>
|
||||
<Traversal.Component
|
||||
<Expression.Component
|
||||
context={context}
|
||||
onChange={(traversalValue, event) => (
|
||||
onChange={(expressionValue, event) => (
|
||||
onChange({
|
||||
...value,
|
||||
traversals: [
|
||||
...traversals.slice(0, i),
|
||||
expressions: [
|
||||
...expressions.slice(0, i),
|
||||
{
|
||||
...traversals[i],
|
||||
...traversalValue,
|
||||
...expressions[i],
|
||||
...expressionValue,
|
||||
},
|
||||
...traversals.slice(i + 1),
|
||||
...expressions.slice(i + 1),
|
||||
],
|
||||
}, event)
|
||||
)}
|
||||
type="any"
|
||||
value={traversal}
|
||||
value={expression}
|
||||
/>
|
||||
</li>
|
||||
),
|
||||
|
@ -53,12 +53,12 @@ const Actions = ({
|
|||
);
|
||||
};
|
||||
|
||||
Actions.propTypes = {
|
||||
Expressions.propTypes = {
|
||||
...propTypes,
|
||||
value: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
export default {
|
||||
type: 'actions',
|
||||
Component: decorate(Actions),
|
||||
type: 'expressions',
|
||||
Component: decorate(Expressions),
|
||||
};
|
|
@ -5,7 +5,7 @@ import React from 'react';
|
|||
import useTypeRenderers from '~/client/hooks/useTypeRenderers';
|
||||
|
||||
import propTypes from './prop-types';
|
||||
import {defaultSteps, stepsOptions, typeFromLiteral} from './typing';
|
||||
import {defaultOps, opsOptions} from './typing';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./literal.raw.scss')),
|
||||
|
@ -14,12 +14,12 @@ const decorate = compose(
|
|||
const Literal = ({
|
||||
context,
|
||||
onChange = () => {},
|
||||
type,
|
||||
value,
|
||||
}) => {
|
||||
const typeRenderers = useTypeRenderers();
|
||||
const type = typeFromLiteral(value.value);
|
||||
const Component = typeRenderers[type];
|
||||
const [options] = stepsOptions(context, [], type);
|
||||
const [options] = opsOptions(context, [], type);
|
||||
options.push('<literal>');
|
||||
return (
|
||||
<div className="literal">
|
||||
|
@ -27,9 +27,9 @@ const Literal = ({
|
|||
onChange={(event) => {
|
||||
if ('<literal>' !== event.target.value) {
|
||||
onChange({
|
||||
type: 'traversal',
|
||||
steps: defaultSteps(context, type, [{type: 'key', key: event.target.value}]),
|
||||
});
|
||||
type: 'expression',
|
||||
ops: defaultOps(context, type, [{type: 'key', key: event.target.value}]),
|
||||
}, event);
|
||||
}
|
||||
}}
|
||||
value="<literal>"
|
||||
|
@ -40,7 +40,7 @@ const Literal = ({
|
|||
.map((option) => <option key={option}>{option}</option>)
|
||||
}
|
||||
</select>
|
||||
{Component ? <Component onChange={onChange} value={value.value} /> : null}
|
||||
{Component ? <Component onChange={onChange} type={type} value={value.value} /> : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
|
||||
import propTypes from './prop-types';
|
||||
import Actions from './actions.type-renderer';
|
||||
import Expressions from './expressions.type-renderer';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./routines.raw.scss')),
|
||||
|
@ -15,8 +15,7 @@ const Routines = ({
|
|||
onChange = () => {},
|
||||
value = {},
|
||||
}) => {
|
||||
const {routines = {}} = value;
|
||||
const entries = Object.entries(routines);
|
||||
const entries = Object.entries(value);
|
||||
return (
|
||||
<div className="routines">
|
||||
<ol>
|
||||
|
@ -27,23 +26,15 @@ const Routines = ({
|
|||
<li className="routine" key={name}>
|
||||
<label>
|
||||
<span className="text">{name}</span>
|
||||
<Actions.Component
|
||||
<Expressions.Component
|
||||
context={context}
|
||||
onChange={(actionsValue, event) => (
|
||||
onChange={(expressions, event) => (
|
||||
onChange({
|
||||
...value,
|
||||
routines: {
|
||||
...routines,
|
||||
[name]: {
|
||||
...routine,
|
||||
routine: {
|
||||
...actionsValue,
|
||||
},
|
||||
},
|
||||
},
|
||||
[name]: expressions,
|
||||
}, event)
|
||||
)}
|
||||
value={routine.routine}
|
||||
value={routine}
|
||||
/>
|
||||
</label>
|
||||
</li>
|
||||
|
|
|
@ -1,138 +1,63 @@
|
|||
import {Context} from '@avocado/behavior';
|
||||
import {Traversal} from '@avocado/behavior/item/traversal';
|
||||
import {
|
||||
candidates as typeCandidates,
|
||||
compile,
|
||||
description as typeDescription,
|
||||
fitsInto,
|
||||
} from '@avocado/behavior';
|
||||
|
||||
let digraph;
|
||||
// eslint-disable-next-line no-return-assign
|
||||
const cachedDigraph = () => (digraph || (digraph = Context.allTypesInvertedDigraph()));
|
||||
|
||||
export function isBehaviorItem(valueOrItem) {
|
||||
if ('object' !== typeof valueOrItem) {
|
||||
return false;
|
||||
}
|
||||
return -1 !== [
|
||||
'actions',
|
||||
'literal',
|
||||
'routines',
|
||||
'traversal',
|
||||
].indexOf(valueOrItem.type);
|
||||
}
|
||||
|
||||
export function toBehaviorItem(valueOrItem) {
|
||||
return isBehaviorItem(valueOrItem) ? valueOrItem : {type: 'literal', value: valueOrItem};
|
||||
}
|
||||
|
||||
export function typeFromLiteral(value) {
|
||||
if ('undefined' === typeof value) {
|
||||
return 'undefined';
|
||||
}
|
||||
if (null === value) {
|
||||
return 'null';
|
||||
}
|
||||
if ('number' === typeof value) {
|
||||
return 'number';
|
||||
}
|
||||
if ('string' === typeof value) {
|
||||
return 'string';
|
||||
}
|
||||
if ('boolean' === typeof value) {
|
||||
return 'bool';
|
||||
}
|
||||
if (value.length && 2 === value.length && value instanceof Array) {
|
||||
return 'vector';
|
||||
}
|
||||
return 'object';
|
||||
}
|
||||
|
||||
const fakeContextDescription = (context) => {
|
||||
const children = Object.entries(context.all())
|
||||
.reduce((r, [key, tuple]) => ({...r, [key]: {type: tuple[1]}}), {});
|
||||
return {children};
|
||||
};
|
||||
|
||||
const stepsValue = (context, steps) => (
|
||||
steps.length > 0 ? (new Traversal({steps})).get(context) : undefined
|
||||
);
|
||||
|
||||
export function descriptionFromSteps(context, steps) {
|
||||
let description = fakeContextDescription(context);
|
||||
if (0 === steps.length) {
|
||||
export function descriptionFromOps(context, ops) {
|
||||
let description = context.description();
|
||||
if (0 === ops.length) {
|
||||
return description;
|
||||
}
|
||||
const isInvocation = 'invoke' === steps[steps.length - 1].type;
|
||||
const keyStepsCount = steps.length - (isInvocation ? 1 : 0);
|
||||
let variable;
|
||||
for (let i = 0; i < keyStepsCount; ++i) {
|
||||
const {children = {}} = description;
|
||||
const {key} = steps[i];
|
||||
variable = stepsValue(context, steps.slice(0, i + 1));
|
||||
for (let i = 0; i < ops.length; ++i) {
|
||||
if ('invoke' === ops[i].type) {
|
||||
continue;
|
||||
}
|
||||
const {children} = description;
|
||||
const {key} = ops[i];
|
||||
const evaluate = compile({type: 'expression', ops: ops.slice(0, i + 1)});
|
||||
variable = evaluate(context);
|
||||
if ('function' === typeof variable && children[key] && children[key].args) {
|
||||
description = children[key];
|
||||
const {type} = children[key];
|
||||
description = {
|
||||
...typeDescription(type),
|
||||
...children[key],
|
||||
};
|
||||
}
|
||||
else {
|
||||
const candidateDescription = Context.typeDescription(
|
||||
description = typeDescription(
|
||||
children[key].type,
|
||||
'function' !== typeof variable || (children[key] && 'function' === children[key].type)
|
||||
'function' !== typeof variable || 'function' === children[key].type
|
||||
? variable
|
||||
: undefined,
|
||||
);
|
||||
description = 0 !== Object.keys(candidateDescription.children || {}).length
|
||||
? candidateDescription
|
||||
: children[key];
|
||||
}
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
export function typeFits(reference, candidate) {
|
||||
return 'any' === reference || -1 !== (reference.split('|') || []).indexOf(candidate);
|
||||
}
|
||||
|
||||
const descriptionCandidates = (description, type) => {
|
||||
const inverted = cachedDigraph();
|
||||
const candidates = (inverted[type] || []).concat(type);
|
||||
const {children = {}} = description;
|
||||
return 'any' === type
|
||||
? Object.keys(children)
|
||||
: Object.entries(children)
|
||||
.reduce((r, [key, spec]) => (
|
||||
candidates.find((candidate) => typeFits(candidate, spec.type))
|
||||
? r.concat(key)
|
||||
: r
|
||||
), []);
|
||||
};
|
||||
|
||||
export function stepsOptions(context, steps, type) {
|
||||
const optionsList = [
|
||||
descriptionCandidates(
|
||||
fakeContextDescription(context),
|
||||
type,
|
||||
),
|
||||
];
|
||||
if (0 === steps.length) {
|
||||
export function opsOptions(context, ops, type) {
|
||||
const optionsList = [typeCandidates(context.description(), type)];
|
||||
if (0 === ops.length) {
|
||||
return optionsList;
|
||||
}
|
||||
const isInvocation = 'invoke' === steps[steps.length - 1].type;
|
||||
const keyStepsCount = steps.length - (isInvocation ? 1 : 0);
|
||||
for (let i = 1; i < keyStepsCount; ++i) {
|
||||
optionsList.push(descriptionCandidates(
|
||||
descriptionFromSteps(context, steps.slice(0, i)),
|
||||
type,
|
||||
));
|
||||
const isInvocation = 'invoke' === ops[ops.length - 1].type;
|
||||
const keyOpsCount = ops.length - (isInvocation ? 1 : 0);
|
||||
for (let i = 1; i < keyOpsCount; ++i) {
|
||||
optionsList.push(typeCandidates(descriptionFromOps(context, ops.slice(0, i)), type));
|
||||
}
|
||||
return optionsList;
|
||||
}
|
||||
|
||||
export function typeFromSteps(context, steps) {
|
||||
return 0 === steps.length ? 'undefined' : descriptionFromSteps(context, steps).type;
|
||||
}
|
||||
|
||||
const defaultInvocation = (context, steps) => {
|
||||
const funcDescription = descriptionFromSteps(context, steps);
|
||||
const defaultInvocation = (context, ops) => {
|
||||
const funcDescription = descriptionFromOps(context, ops);
|
||||
const {args = []} = funcDescription;
|
||||
return {
|
||||
type: 'invoke',
|
||||
args: args.map(([, {type}]) => {
|
||||
const {defaultLiteral} = Context.typeDescription(type, undefined);
|
||||
const {defaultLiteral} = typeDescription(type, undefined);
|
||||
if ('undefined' !== defaultLiteral) {
|
||||
return ({
|
||||
type: 'literal',
|
||||
|
@ -140,53 +65,56 @@ const defaultInvocation = (context, steps) => {
|
|||
});
|
||||
}
|
||||
return ({
|
||||
type: 'traversal',
|
||||
type: 'expression',
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
steps: defaultSteps(context, type),
|
||||
ops: defaultOps(context, type),
|
||||
});
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
export const defaultSteps = (context, type, originalSteps = []) => {
|
||||
const steps = [...originalSteps];
|
||||
let stepsType = typeFromSteps(context, originalSteps);
|
||||
const typesVisited = {[stepsType]: true};
|
||||
while (!typeFits(type, stepsType) || 0 === steps.length) {
|
||||
if ('function' === typeof stepsValue(context, steps)) {
|
||||
export const defaultOps = (context, type, originalOps = []) => {
|
||||
const ops = [...originalOps];
|
||||
let evaluated;
|
||||
let {type: opsType} = descriptionFromOps(context, originalOps);
|
||||
const typesVisited = {[opsType]: true};
|
||||
while (!fitsInto(opsType, type) || 0 === ops.length) {
|
||||
evaluated = compile({type: 'expression', ops})(context);
|
||||
if (
|
||||
'invoke' !== ops[ops.length - 1].type
|
||||
&& 'function' === typeof evaluated
|
||||
) {
|
||||
if ('function' === type) {
|
||||
return steps;
|
||||
return ops;
|
||||
}
|
||||
steps.push(defaultInvocation(context, steps));
|
||||
ops.push(defaultInvocation(context, ops));
|
||||
}
|
||||
else {
|
||||
const description = descriptionFromSteps(context, steps);
|
||||
const description = descriptionFromOps(context, ops);
|
||||
const {children = {}} = description;
|
||||
const candidates = descriptionCandidates(description, type);
|
||||
const candidates = typeCandidates(description, type);
|
||||
const key = candidates.find((candidate) => {
|
||||
const {type: candidateType} = children[candidate];
|
||||
if (typesVisited[candidateType]) {
|
||||
return false;
|
||||
}
|
||||
if (typeFits(type, candidateType)) {
|
||||
if (fitsInto(type, candidateType)) {
|
||||
return true;
|
||||
}
|
||||
typesVisited[candidateType] = true;
|
||||
return true;
|
||||
});
|
||||
steps.push({type: 'key', key});
|
||||
if ('function' === typeof stepsValue(context, steps)) {
|
||||
steps.push(defaultInvocation(context, steps));
|
||||
ops.push({type: 'key', key});
|
||||
evaluated = compile({type: 'expression', ops})(context);
|
||||
if ('function' === typeof evaluated) {
|
||||
ops.push(defaultInvocation(context, ops));
|
||||
}
|
||||
}
|
||||
stepsType = typeFromSteps(context, steps);
|
||||
opsType = descriptionFromOps(context, ops).type;
|
||||
}
|
||||
if ('function' === typeof stepsValue(context, steps)) {
|
||||
steps.push(defaultInvocation(context, steps));
|
||||
evaluated = compile({type: 'expression', ops})(context);
|
||||
if ('function' === typeof evaluated) {
|
||||
ops.push(defaultInvocation(context, ops));
|
||||
}
|
||||
return steps;
|
||||
return ops;
|
||||
};
|
||||
|
||||
export function typeFromValue(v) {
|
||||
return isBehaviorItem(v) ? v.type : undefined;
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@ const Vector = ({
|
|||
}) => (
|
||||
<span className="vector">
|
||||
<Number.Component
|
||||
onChange={(axe) => onChange([axe, value[1]])}
|
||||
onChange={(axe, event) => onChange([axe, value[1]], event)}
|
||||
value={value[0]}
|
||||
/>
|
||||
<span className="separator">{' x '}</span>
|
||||
<Number.Component
|
||||
onChange={(axe) => onChange([value[0], axe])}
|
||||
onChange={(axe, event) => onChange([value[0], axe], event)}
|
||||
value={value[1]}
|
||||
/>
|
||||
</span>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {isCompilable} from '@avocado/behavior';
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import useTypeRenderers from '~/client/hooks/useTypeRenderers';
|
||||
import {typeFromLiteral, typeFromValue} from '~/client/types/typing';
|
||||
|
||||
import propTypes from './types/prop-types';
|
||||
|
||||
|
@ -16,19 +16,11 @@ const Value = ({
|
|||
context,
|
||||
onChange = () => {},
|
||||
options,
|
||||
type: typeHint,
|
||||
type,
|
||||
value,
|
||||
}) => {
|
||||
const typeRenderers = useTypeRenderers();
|
||||
const fromValue = typeFromValue(value);
|
||||
let type;
|
||||
if (typeHint) {
|
||||
type = typeHint;
|
||||
}
|
||||
else {
|
||||
type = 'undefined' !== typeof fromValue ? fromValue : typeFromLiteral(value);
|
||||
}
|
||||
const Component = typeRenderers[fromValue || type];
|
||||
const Component = typeRenderers[isCompilable(value) ? value.type : type];
|
||||
return (
|
||||
<span className="value">
|
||||
{
|
||||
|
|
|
@ -5929,6 +5929,11 @@ lodash.mapvalues@4.6.0:
|
|||
resolved "https://npm.i12e.cha0s.io/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c"
|
||||
integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://npm.i12e.cha0s.io/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
|
||||
|
||||
lodash.mergewith@4.6.1:
|
||||
version "4.6.1"
|
||||
resolved "https://npm.i12e.cha0s.io/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
|
||||
|
|
Loading…
Reference in New Issue
Block a user