chore: ded

This commit is contained in:
cha0s 2021-07-09 12:50:17 -05:00
parent 250f057d0c
commit b8d775eaa6
13 changed files with 0 additions and 1419 deletions

View File

@ -1,131 +0,0 @@
import './condition.scss';
import {join} from 'path';
import {useJsonPatcher} from '@avocado/resource-persea';
import {
classnames,
PropTypes,
React,
} from '@latus/react';
import Variant from './help/variant';
const Condition = ({context, path, value}) => {
const patch = useJsonPatcher();
const operands = value.operands.map((operand, i) => {
const operandKey = join(path, 'operands', i.toString());
return (
<Variant
context={context}
key={operandKey}
onChange={(event, value, localPath) => {
patch({
path: localPath,
value,
});
}}
path={operandKey}
type="any"
value={operand}
/>
);
});
const operator = (
<select
key={join(path, 'operator')}
onChange={(event) => {
patch({
path: join(path, 'operator'),
value: event.target.value,
});
}}
value={value.operator}
>
<option value="is">is</option>
<option value="isnt">isnt</option>
<option value=">">&gt;</option>
<option value=">=">&gt;=</option>
<option value="<">&lt;</option>
<option value="<=">&lt;=</option>
<option value="or">or</option>
<option value="and">and</option>
<option value="contains">contains</option>
</select>
);
const renderables = [];
switch (value.operator) {
case 'or':
case 'and':
renderables.push(operator);
renderables.push(...operands.map((operand, i) => (
<div className="operand__wrapper">
{operand}
<button
className="condition__remove-operand"
onClick={() => {
patch({
op: 'remove',
path: join(path, 'operands', i.toString()),
});
}}
type="button"
>
x
</button>
</div>
)));
renderables.push(
<button
onClick={() => {
patch({
op: 'add',
path: join(path, 'operands/-'),
value: {
type: 'literal',
value: true,
},
});
}}
type="button"
>
Add operand
</button>,
);
break;
default:
renderables.push(operands.shift());
renderables.push(operator);
renderables.push(...operands);
}
return (
<div
className={classnames(
'condition',
{'condition--vertical': -1 !== ['and', 'or'].indexOf(value.operator)},
)}
>
{renderables}
</div>
);
};
Condition.defaultProps = {};
Condition.displayName = 'Condition';
Condition.propTypes = {
context: PropTypes.shape({
describeChildren: PropTypes.func,
get: PropTypes.func,
}).isRequired,
path: PropTypes.string.isRequired,
value: PropTypes.shape({
operator: PropTypes.string,
operands: PropTypes.arrayOf(
PropTypes.any,
),
}).isRequired,
};
export default Condition;

View File

@ -1,49 +0,0 @@
.condition {
align-items: center;
display: flex;
&.condition--vertical {
align-items: flex-start;
flex-direction: column;
}
}
.condition--vertical {
> select {
margin-bottom: 1em;
}
> .expression,
> .key,
> .literal {
margin-left: 1em;
}
> .expression {
margin-bottom: 0.5em;
&:last-child {
margin-bottom: 0;
}
}
}
.condition .condition--vertical {
padding-top: 0.5em;
}
.operand__wrapper {
align-items: center;
display: flex;
padding-left: 0.5em;
width: 100%;
&:nth-of-type(2n+1) {
background-color: rgba(255, 255, 255, 0.05);
}
> button {
background-color: transparent;
border: none;
font-size: 0.8em;
margin-left: auto;
margin-right: 0.5em;
padding: 1em;
pointer-events: auto;
}
}

View File

@ -1,367 +0,0 @@
import './expression.scss';
import {join, relative} from 'path';
import {useJsonPatcher} from '@avocado/resource-persea';
import {
classnames,
PropTypes,
React,
useLatus,
} from '@latus/react';
import compile from '../../compilers/compile';
import {isInvocation, isKey} from '../../testers';
import Invocation from './expression/invocation';
import Key from './expression/key';
import Variant from './help/variant';
const Expression = ({
context,
path,
type,
value,
vararg,
}) => {
const latus = useLatus();
const patch = useJsonPatcher();
const types = latus.get('%behavior-types');
let i = 0;
const {ops, value: expressionValue} = value;
const Renderables = [];
let opsCount = 0;
// eslint-disable-next-line react/destructuring-assignment
let description = context.describeChildren();
const onChange = (event, value, localPath) => {
const patches = [];
const j = parseInt(relative(path, localPath).split('/')[1], 10);
if (j < ops.length - 1) {
for (let k = j + 1; k < ops.length; ++k) {
patches.unshift({
op: 'remove',
path: join(path, 'ops', k.toString()),
});
}
}
else if (event && j === ops.length) {
patches.push({
op: 'add',
path: join(path, 'ops', j.toString()),
value: {
type: 'key',
},
});
}
patches.push({
path: localPath,
value,
});
patch(patches);
};
do {
const op = ops[i];
const opPath = join(path, 'ops', opsCount.toString());
const nextOp = i === ops.length - 1 ? undefined : ops[i + 1];
if (isKey(op)) {
const isFirst = 0 === i;
const isLast = i === ops.length - 1 ? true : isInvocation(ops[i + 1]);
Renderables.push(
<Key
childrenDescription={{
...(
isFirst && 'void' !== type
? {
'[literal]': {label: '', type},
}
: {}
),
...(
vararg && isFirst
? {'...': {label: '', type: description.type}}
: {}
),
...(
isLast && !isFirst
? {'.': {label: '', type: description.type}}
: {}
),
...description.children,
...(
isFirst
? {
'[key]': {label: '', type: 'undefined'},
}
: {
'[key]': {label: '', type: 'undefined'},
'[invoke]': {label: '', type: 'undefined'},
}
),
}}
key={opPath}
onChange={((i) => (event, value, localPath) => {
if ('.' === value || '...' === value) {
const parts = localPath.split('/');
parts.pop();
parts.pop();
if ('...' === value) {
parts.pop();
patch({
op: 'remove',
path: parts.join('/'),
});
return;
}
const patches = [];
for (let j = i; j < ops.length; ++j) {
patches.unshift(
{
op: 'remove',
path: join(parts.join('/'), j.toString()),
},
);
}
patch(patches);
}
else if ('[literal]' === value) {
patch({
op: 'replace',
path,
value: {
type: 'literal',
value: null,
},
});
}
else {
onChange(event, value, localPath);
}
})(i)}
path={opPath}
value={op.key}
/>,
);
opsCount += 1;
}
if (isInvocation(op)) {
const R = Renderables.pop();
Renderables.push(
<div
className="expression__invocation-toggle-wrapper"
key={`${opPath}-toggle-from`}
>
{R}
<button
className="expression__invocation-toggle from"
onClick={() => {
patch({
op: 'remove',
path: opPath,
});
}}
type="button"
>
</button>
</div>,
);
Renderables.push(
<Invocation
context={context}
description={description}
Expression={Expression}
key={opPath}
onChange={onChange}
op={op}
path={opPath}
/>,
);
opsCount += 1;
}
if (isKey(op)) {
const current = compile({type: 'expression', ops: ops.slice(0, i + 1)}, latus)(context);
description = description.children?.[op.key] || {type: 'undefined'};
const {args, type} = description;
if ('void' !== type) {
description = {
...context.constructor.descriptionFor(
type,
current,
latus,
),
...(args ? {args} : {}),
};
}
if (description.args && (!nextOp || !isInvocation(nextOp))) {
const R = Renderables.pop();
Renderables.push(
<div
className="expression__invocation-toggle-wrapper"
key={`${opPath}-toggle-to`}
>
{R}
<button
className="expression__invocation-toggle to"
onClick={((description, opPath) => () => {
const parts = opPath.split('/');
parts.push(parseInt(parts.pop(), 10) + 1);
patch({
op: 'add',
path: parts.join('/'),
value: {
type: 'invoke',
args: description.vararg
? []
: description.args.map(
(arg) => ({
...(false === arg.compile ? {compile: false} : {}),
...(
(types[arg.type] || types.undefined).create(
(arg.options?.length || 0) > 0
? arg.options[0].value
: undefined,
)
),
}),
),
},
});
})(description, opPath)}
type="button"
>
</button>
</div>,
);
}
}
if (isInvocation(op)) {
if ('void' !== description.type) {
description = context.constructor.descriptionFor(
description.type,
undefined,
latus,
);
}
}
} while (i++ < ops.length - 1);
if (
description.children
|| 'undefined' === description.type
) {
const opPath = join(path, 'ops', opsCount.toString());
Renderables.push(
<Key
childrenDescription={{
'.': {label: '', type: description.type},
...(description.children || {}),
'[key]': {label: '', type: 'undefined'},
'[invoke]': {label: '', type: 'undefined'},
}}
key={opPath}
onChange={onChange}
path={opPath}
value="."
/>,
);
opsCount += 1;
}
const [lastOp] = ops.slice(-1);
if (
'void' === type
&& isKey(lastOp)
) {
const opPath = join(path, 'value');
Renderables.push(
<Key
childrenDescription={{
'≡': {label: '', type: description.type},
'≔': {label: '', type: 'void'},
}}
key={opPath}
onChange={(event, value) => {
if ('≡' === value) {
patch({
op: 'remove',
path: opPath,
});
}
else {
patch({
path: opPath,
value: (types[description.type] || types.undefined).create(),
});
}
}}
path={opPath}
value={expressionValue ? '≔' : '≡'}
/>,
);
if (expressionValue) {
const expressionType = isKey(lastOp) && description.args
? 'function'
: description.type;
Renderables.push(
<Variant
context={context}
onChange={(event, value, localPath) => {
patch({
path: localPath,
value,
});
}}
key={join(opPath, 'expression')}
path={opPath}
type={expressionType}
value={expressionValue}
vararg={vararg}
/>,
);
}
}
let realType = description.type;
if (isKey(lastOp) && description.args) {
realType = 'function';
}
if (expressionValue) {
realType = 'undefined' === description.type ? 'undefined' : 'void';
}
return (
<div
className={classnames(
'expression',
{'wrong-type': 'any' !== type && 'undefined' !== type && realType !== type},
{'undefined-type': 'undefined' === realType},
)}
>
{Renderables}
</div>
);
};
Expression.defaultProps = {
vararg: false,
};
Expression.displayName = 'Expression';
Expression.propTypes = {
context: PropTypes.shape({
constructor: PropTypes.func,
describeChildren: PropTypes.func,
get: PropTypes.func,
}).isRequired,
value: PropTypes.shape({
ops: PropTypes.arrayOf(
PropTypes.shape({
key: PropTypes.string,
}),
),
// eslint-disable-next-line react/forbid-prop-types
value: PropTypes.any,
}).isRequired,
vararg: PropTypes.bool,
path: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
};
export default Expression;

View File

@ -1,37 +0,0 @@
.expression {
align-items: center;
display: flex;
flex-wrap: wrap;
button, .button {
color: #00bdd6;
}
&.wrong-type {
background-color: rgb(180, 0, 0);
padding: 0.5em;
}
&.undefined-type {
background-color: rgb(180, 180, 0);
padding: 0.5em;
}
> .expression {
width: auto;
}
}
.expression__invocation-toggle-wrapper {
align-items: center;
display: flex;
}
.expression__invocation-toggle {
background: #222222;
margin: 0;
padding: 0.25em;
pointer-events: auto;
&:hover {
background: #333333;
}
&.to {
transform: rotate(180deg);
}
}

View File

@ -1,137 +0,0 @@
import './invocation.scss';
import {join} from 'path';
import {useJsonPatcher} from '@avocado/resource-persea';
import {
PropTypes,
React,
} from '@latus/react';
import Variant from '../help/variant';
import Key from './key';
const Invocation = ({
context,
description,
onChange,
op,
path,
}) => {
const patch = useJsonPatcher();
const argComponent = (arg, i) => {
const argPath = join(path, 'args', i.toString());
if ('undefined' === arg.type) {
return (
<Key
childrenDescription={{
'...': {label: '', type: 'undefined'},
'[literal]': {label: '', type: 'undefined'},
...context.describeChildren().children,
'[key]': {label: '', type: 'undefined'},
}}
key={path}
onChange={(event, value) => {
if ('[literal]' === value) {
patch({
type: 'add',
path: argPath,
value: {
type: 'literal',
value: null,
},
});
return;
}
patch({
type: 'add',
path: argPath,
value: {
type: 'expression',
ops: [
{
type: 'key',
},
],
},
});
onChange(false, value, join(argPath, 'ops/0/key'));
}}
path={argPath}
value="..."
/>
);
}
let darg;
if ('function' === typeof description?.args) {
darg = description?.args(i);
}
else {
const j = description.vararg ? i % description?.args?.length : i;
darg = description?.args?.[j];
}
const type = darg?.type || 'undefined';
return (
<Variant
context={context}
onChange={onChange}
options={darg?.options}
path={argPath}
type={type}
value={arg}
vararg={
'undefined' === type
|| description.vararg
}
/>
);
};
const isVarArg = 'undefined' === description.type || description.vararg;
const args = op.args.concat();
if (isVarArg) {
args.push({type: 'undefined'});
}
return (
<div className="invocation">
{args.length > 0 && (
<div className="invocation__args-wrapper">
{
args.map((arg, i) => (
<div
key={join(path, 'args', i.toString())}
className="invocation__arg"
>
{argComponent(arg, i)}
</div>
))
}
</div>
)}
</div>
);
};
Invocation.displayName = 'Invocation';
Invocation.propTypes = {
context: PropTypes.shape({
describeChildren: PropTypes.func,
}).isRequired,
description: PropTypes.shape({
args: PropTypes.arrayOf(
PropTypes.shape({
options: PropTypes.arrayOf(PropTypes.any),
type: PropTypes.string,
}),
),
type: PropTypes.string,
vararg: PropTypes.bool,
}).isRequired,
onChange: PropTypes.func.isRequired,
op: PropTypes.shape({
args: PropTypes.arrayOf(PropTypes.any),
}).isRequired,
path: PropTypes.string.isRequired,
};
export default Invocation;

View File

@ -1,53 +0,0 @@
.invocation {
align-items: center;
display: flex;
margin-left: 0.25em;
> .expression {
margin: 0 0.5em;
}
&:after {
color: #00bdd6;
content: ')';
font-size: 1.5em;
}
&:before {
color: #00bdd6;
content: '(';
font-size: 1.5em;
}
}
.invocation__args-wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0.25em;
}
.invocation__arg {
align-items: center;
background-color: rgba(255, 255, 255, 0.1);
display: flex;
padding: 0.5em;
position: relative;
&:nth-of-type(2n+1) {
background-color: rgba(0, 0, 0, 0.1);
}
&:after {
color: #00bdd6;
content: ',';
font-size: 1.5em;
position: absolute;
bottom: 0;
right: 0;
}
&:last-of-type {
&::after {
content: '';
}
}
}
.invocation__arg-sep {
align-self: flex-end;
}

View File

@ -1,140 +0,0 @@
import './key.scss';
import {join} from 'path';
import {useJsonPatcher} from '@avocado/resource-persea';
import {
PropTypes,
React,
useEffect,
useRef,
useState,
} from '@latus/react';
import natsort from 'natsort';
const sorter = natsort({insensitive: true});
const Key = ({
childrenDescription,
onChange,
path,
value,
}) => {
const patch = useJsonPatcher();
const customizeRef = useRef();
const [customization, setCustomization] = useState(false);
const [customizationPath, setCustomizationPath] = useState('/');
useEffect(() => {
customizeRef.current?.focus();
});
const optionKeys = Object.entries(childrenDescription).map(([key]) => key);
if (-1 === optionKeys.indexOf(value)) {
optionKeys.unshift(value);
}
const options = optionKeys
.sort(sorter)
.map((key) => (
<option key={key} value={key}>{key}</option>
));
const confirmCustomization = () => {
const parts = customizationPath.split('/');
parts.pop();
setCustomization(false);
setCustomizationPath('/');
if ('value' === parts[parts.length - 1]) {
patch({
type: 'add',
path: parts.join('/'),
value: {
type: 'expression',
ops: [
{
type: 'key',
key: customization,
},
],
},
});
}
else {
patch({
type: 'add',
path: parts.join('/'),
value: {
type: 'key',
},
});
onChange(false, customization, join(parts.join('/'), 'key'));
}
};
return (
<div
className="key"
>
{
false === customization
? (
<select
className="key__selector"
onChange={(event) => {
const localPath = join(path, 'key');
const {target: {value}} = event;
switch (value) {
case '[key]': {
setCustomization('');
setCustomizationPath(localPath);
break;
}
case '[invoke]': {
const parts = localPath.split('/');
parts.pop();
patch({
type: 'add',
path: parts.join('/'),
value: {
type: 'invoke',
args: [],
},
});
break;
}
default:
onChange(event, value, localPath);
}
}}
value={value}
>
{options}
</select>
)
: (
<input
type="text"
onBlur={confirmCustomization}
onChange={({target: {value}}) => {
setCustomization(value);
}}
onKeyPress={(event) => {
if ('Enter' === event.key) {
confirmCustomization(event);
}
}}
ref={customizeRef}
value={customization}
/>
)
}
</div>
);
};
Key.displayName = 'Key';
Key.propTypes = {
childrenDescription: PropTypes.shape({}).isRequired,
onChange: PropTypes.func.isRequired,
path: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
};
export default Key;

View File

@ -1,3 +0,0 @@
.key__selector {
pointer-events: auto;
}

View File

@ -1,149 +0,0 @@
import './expressions.scss';
import {join} from 'path';
import {useJsonPatcher} from '@avocado/resource-persea';
import {
PropTypes,
React,
useLatus,
} from '@latus/react';
import compile from '../../compilers/compile';
import Expression from './expression';
const Expressions = ({
context,
value: {expressions},
path,
}) => {
const latus = useLatus();
const patch = useJsonPatcher();
const createExpressionSwapper = (l, r) => () => {
const le = expressions[l];
const re = expressions[r];
patch([
{
path: join(path, 'expressions', l.toString()),
value: re,
},
{
path: join(path, 'expressions', r.toString()),
value: le,
},
]);
};
let currentContext = context;
return (
<div className="expressions">
{
expressions.map((expression, i) => {
currentContext = currentContext.clone();
const {ops} = expression;
if (3 === ops.length && 'context' === ops[0].key && 'add' === ops[1].key) {
const [key, value] = ops[2].args;
if ('undefined' !== key.type && 'undefined' !== value.type) {
currentContext.add(
compile(key, latus)(currentContext),
compile(value, latus)(currentContext),
);
}
}
const expressionPath = join(path, 'expressions', i.toString());
return (
<div
className="expressions__expression-wrapper"
key={expressionPath}
>
<div className="expressions__move-expression">
{i > 0 && (
<button
className="expressions__move-expression-up"
onClick={createExpressionSwapper(i, i - 1)}
type="button"
>
🠹
</button>
)}
<div className="expressions__move-expression-spacer" />
{i < expressions.length - 1 && (
<button
className="expressions__move-expression-down"
onClick={createExpressionSwapper(i, i + 1)}
type="button"
>
🠻
</button>
)}
</div>
<Expression
context={currentContext}
value={expression}
path={expressionPath}
type="void"
/>
<button
className="expressions__remove-expression"
onClick={() => {
patch({
op: 'remove',
path: expressionPath,
});
}}
type="button"
>
x
</button>
</div>
);
})
}
<div className="expressions__expression-wrapper">
<button
className="expressions__add-expression"
onClick={() => {
patch({
op: 'add',
path: join(path, 'expressions/-'),
value: {
type: 'expression',
ops: [
{
type: 'key',
key: 'Flow',
},
{
type: 'key',
key: 'nop',
},
{
type: 'invoke',
args: [],
},
],
},
});
}}
type="button"
>
Add expression
</button>
</div>
</div>
);
};
Expressions.displayName = 'Expressions';
Expressions.propTypes = {
context: PropTypes.shape({}).isRequired,
value: PropTypes.shape({
type: PropTypes.string,
expressions: PropTypes.arrayOf(
PropTypes.shape({}),
),
}).isRequired,
path: PropTypes.string.isRequired,
};
export default Expressions;

View File

@ -1,54 +0,0 @@
.expressions__expression-wrapper {
align-items: center;
background-color: rgba(0, 0, 0, 0.05);
display: flex;
&:nth-of-type(2n+1) {
background-color: rgba(255, 255, 255, 0.05);
}
button, .button {
color: #00bdd6;
}
}
.expressions__move-expression {
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 0.5em;
}
.expressions__move-expression-up,
.expressions__move-expression-down {
margin: 0;
padding: 0 0.5em;
pointer-events: auto;
}
.expressions__move-expression-up
+ .expressions__move-expression-spacer
+ .expressions__move-expression-down {
margin-top: 0.5em;
}
.expressions__expression-wrapper > .expression {
margin-right: 0.5em;
padding: 0.5em;
width: 100%;
}
.expressions__remove-expression {
background-color: transparent;
border: none;
font-size: 0.8em;
margin-left: auto;
margin-right: 0.5em;
padding: 1em;
pointer-events: auto;
}
.expressions__add-expression {
font-size: 0.8em;
margin-left: 0.5em;
margin-right: 0.5em;
pointer-events: auto;
}

View File

@ -1,31 +0,0 @@
import {
PropTypes,
React,
useLatus,
} from '@latus/react';
const Variant = (props) => {
const {value} = props;
const {type} = value;
const latus = useLatus();
const Component = latus.get('%behavior-components')[type];
return (
<Component
value={value}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
/>
);
};
Variant.displayName = 'Variant';
Variant.propTypes = {
onChange: PropTypes.func.isRequired,
path: PropTypes.string.isRequired,
value: PropTypes.shape({
type: PropTypes.string,
}).isRequired,
};
export default Variant;

View File

@ -1,263 +0,0 @@
import './literal.scss';
import {join} from 'path';
import {useJsonPatcher} from '@avocado/resource-persea';
import {
Rectangle,
Vector,
} from '@avocado/math-persea';
import {
Json,
Number,
} from '@avocado/react';
import {
PropTypes,
React,
useLatus,
useState,
} from '@latus/react';
import Context from '../../context';
import Key from './expression/key';
const Literal = ({
context,
onChange,
path,
type,
options,
value,
vararg,
}) => {
const latus = useLatus();
const patch = useJsonPatcher();
const [selectingType, setSelectingType] = useState(false);
const types = latus.get('%behavior-types');
const setLiteralType = (type) => {
const value = (types[type] || types.undefined).create();
if (null !== value) {
patch({
op: 'replace',
path,
value,
});
}
setSelectingType(false);
};
// eslint-disable-next-line react/destructuring-assignment
const contextDescription = context.describeChildren();
const valueComponent = (path, type, {value}) => {
switch (type) {
case 'bool': {
return (
<select
onChange={(event) => {
onChange(event, !!event.target.value, path);
}}
value={null === value ? false : value}
>
<option value={false}>false</option>
<option value>true</option>
</select>
);
}
case 'number':
return (
<Number
onChange={(event, value) => {
onChange(event, value, path);
}}
value={null === value ? 0 : value}
/>
);
case 'string':
return (
<input
type="text"
onChange={(event) => {
onChange(event, event.target.value, path);
}}
value={null === value ? '' : value}
/>
);
case 'object':
return (
<Json
onChange={(event, value) => {
onChange(event, value, path);
}}
json={null === value ? {} : value}
/>
);
case 'vector':
return (
<Vector
onChange={(event, value) => {
onChange(event, value, path);
}}
value={null === value ? [0, 0] : value}
/>
);
case 'rectangle':
return (
<Rectangle
onChange={(event, value) => {
onChange(event, value, path);
}}
value={null === value ? [0, 0, 0, 0] : value}
/>
);
case 'function':
case 'null':
case 'array':
return null;
default: {
const elements = [];
if ('undefined' === type || 'any' === type) {
elements.push(
<select
key={join(path, 'equality')}
onChange={({target: {value}}) => {
setSelectingType('≟' === value);
}}
value={selectingType ? '≟' : '='}
>
<option>=</option>
<option></option>
</select>,
);
}
if ('undefined' !== typeof value) {
elements.push(
<div className="component" key={join(path, 'component')}>
{
valueComponent(
path,
Context.descriptionFor(undefined, value, latus).type,
{value},
)
}
</div>,
);
}
return <>{elements}</>;
}
}
};
const {type: inferred} = Context.descriptionFor(undefined, value.value, latus);
const typeKey = `[literal ${inferred}]`;
return (
<>
{
selectingType
? (
<select
onChange={({target: {value}}) => {
setLiteralType(value);
}}
>
<option>- Select type -</option>
{
Object.entries(types)
.filter(([type, value]) => value.create && type)
.map(([type]) => type)
.map((type) => <option key={type} value={type}>{type}</option>)
}
</select>
)
: (
<Key
childrenDescription={{
...(
'undefined' === type
? {'.': {label: '', type: 'undefined'}}
: {}
),
...(
vararg
? {'...': {label: '', type: 'undefined'}}
: {}
),
[typeKey]: {label: '', type: value.type},
...contextDescription.children,
'[key]': {label: '', type: value.type},
}}
onChange={(event, value) => {
if ('.' === value || '...' === value) {
patch({
op: 'remove',
path,
});
return;
}
patch({
op: 'replace',
path,
value: {
type: 'expression',
ops: [
{
type: 'key',
key: value,
},
],
},
});
}}
path={path}
value={typeKey}
/>
)
}
<div className="literal">
{
options.length > 0
? (
<select
onChange={(event) => {
onChange(event, options[event.target.value].value, join(path, 'value'));
}}
value={options.findIndex(({value: optionValue}) => value.value === optionValue)}
>
{
Object.entries(options)
.map(([key, {label}]) => (
<option
key={label}
value={key}
>
{label}
</option>
))
}
</select>
)
: valueComponent(join(path, 'value'), type, value)
}
</div>
</>
);
};
Literal.defaultProps = {
options: [],
vararg: false,
};
Literal.displayName = 'Literal';
Literal.propTypes = {
context: PropTypes.shape({
describeChildren: PropTypes.func,
}).isRequired,
type: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
options: PropTypes.arrayOf(PropTypes.any),
path: PropTypes.string.isRequired,
// eslint-disable-next-line react/forbid-prop-types
value: PropTypes.any.isRequired,
vararg: PropTypes.bool,
};
export default Literal;

View File

@ -1,5 +0,0 @@
.literal {
align-items: center;
display: flex;
pointer-events: auto;
}