refactor: literal handles its typing

This commit is contained in:
cha0s 2021-01-31 14:12:48 -06:00
parent 67a6caa62d
commit fc25cbe3f5
3 changed files with 169 additions and 130 deletions

View File

@ -3,9 +3,6 @@ import {join} from 'path';
import { import {
PropTypes, PropTypes,
React, React,
useEffect,
useRef,
useState,
} from '@latus/react'; } from '@latus/react';
import {useJsonPatcher} from '@persea/json'; import {useJsonPatcher} from '@persea/json';
@ -19,91 +16,48 @@ const Invocation = ({
op, op,
path, path,
}) => { }) => {
const literalTypeRef = useRef();
const [literalType, setLiteralType] = useState(false);
useEffect(() => {
literalTypeRef.current?.focus();
});
const patch = useJsonPatcher(); const patch = useJsonPatcher();
const argComponent = (arg, i) => { const argComponent = (arg, i) => {
const argPath = join(path, 'args', i.toString()); const argPath = join(path, 'args', i.toString());
if ('undefined' === arg.type) { if ('undefined' === arg.type) {
const confirmLiteralType = () => { return (
let value = null; <Key
switch (literalType) { childrenDescription={{
case 'expressions': '...': {label: '', type: 'undefined'},
value = { '[literal]': {label: '', type: 'undefined'},
type: 'expressions', ...context.describe().children,
expressions: [], '[key]': {label: '', type: 'undefined'},
}; }}
break; key={path}
case 'number': value = 0; break; onChange={(event, value) => {
case 'string': value = ''; break; if ('[literal]' === value) {
case 'array': value = []; break; patch({
case 'object': value = {}; break; type: 'add',
case 'vector': value = [0, 0]; break; path: argPath,
default: value: {
} type: 'literal',
patch({ },
op: 'replace', });
path: argPath, return;
value: { }
type: 'literal', patch({
value, type: 'add',
}, path: argPath,
}); value: {
setLiteralType(false); type: 'expression',
}; ops: [
return false === literalType {
? ( type: 'key',
<Key
childrenDescription={{
'...': {label: '', type: 'undefined'},
'[literal]': {label: '', type: 'undefined'},
...context.describe().children,
'[key]': {label: '', type: 'undefined'},
}}
key={path}
onChange={(event, value) => {
if ('[literal]' === value) {
setLiteralType('');
}
else {
patch({
type: 'add',
path: argPath,
value: {
type: 'expression',
ops: [
{
type: 'key',
},
],
}, },
}); ],
onChange(false, value, join(argPath, 'ops/0/key')); },
} });
}} onChange(false, value, join(argPath, 'ops/0/key'));
path={argPath} }}
value="..." path={argPath}
/> value="..."
) />
: ( );
<input
type="text"
onBlur={confirmLiteralType}
onChange={({target: {value}}) => {
setLiteralType(value);
}}
onKeyPress={(event) => {
if ('Enter' === event.key) {
confirmLiteralType(event);
}
}}
ref={literalTypeRef}
value={literalType}
/>
);
} }
const j = description.vararg ? Math.min(description?.args?.length - 1, i) : i; const j = description.vararg ? Math.min(description?.args?.length - 1, i) : i;
const options = description?.args?.[j].options; const options = description?.args?.[j].options;

View File

@ -1,7 +1,13 @@
import {join} from 'path'; import {join} from 'path';
import {Context} from '@avocado/behavior'; import {Context} from '@avocado/behavior';
import {PropTypes, React} from '@latus/react'; import {
PropTypes,
React,
useEffect,
useRef,
useState,
} from '@latus/react';
import { import {
Number, Number,
Vector, Vector,
@ -23,9 +29,42 @@ const Literal = ({
value, value,
vararg, vararg,
}) => { }) => {
const literalTypeRef = useRef();
const patch = useJsonPatcher();
const [literalType, setLiteralType] = useState(false);
useEffect(() => {
literalTypeRef.current?.focus();
});
const confirmLiteralType = () => {
if (literalType) {
let value = null;
switch (literalType) {
case 'expressions':
value = {
type: 'expressions',
expressions: [],
};
break;
case 'number': value = 0; break;
case 'string': value = ''; break;
case 'array': value = []; break;
case 'object': value = {}; break;
case 'vector': value = [0, 0]; break;
default:
}
patch({
op: 'replace',
path,
value: {
type: 'literal',
value,
},
});
}
setLiteralType(false);
};
// eslint-disable-next-line react/destructuring-assignment // eslint-disable-next-line react/destructuring-assignment
const contextDescription = context.describe(); const contextDescription = context.describe();
const patch = useJsonPatcher();
const valueComponent = (path, type, {value}) => { const valueComponent = (path, type, {value}) => {
switch (type) { switch (type) {
case 'bool': { case 'bool': {
@ -97,55 +136,99 @@ const Literal = ({
case 'null': case 'null':
case 'array': case 'array':
return null; return null;
default: default: {
return 'undefined' !== typeof value const elements = [];
? valueComponent(path, Context.inferTypeOf(value), {value}) if ('undefined' === type || 'any' === type) {
: null; elements.push(
<select
key={join(path, 'equality')}
onChange={({target: {value}}) => {
if ('≟' === value) {
setLiteralType('');
}
}}
value={false === literalType ? '=' : '≟'}
>
<option>=</option>
<option></option>
</select>,
);
}
if ('undefined' !== typeof value) {
elements.push(
<div className="component" key={join(path, 'component')}>
{valueComponent(path, Context.inferTypeOf(value), {value})}
</div>,
);
}
return <>{elements}</>;
}
} }
}; };
return ( return (
<> <>
<Key {
childrenDescription={{ false !== literalType
...( ? (
'undefined' === type <input
? {'.': {label: '', type: 'undefined'}} type="text"
: {} onBlur={confirmLiteralType}
), onChange={({target: {value}}) => {
...( setLiteralType(value);
vararg }}
? {'...': {label: '', type: 'undefined'}} onKeyPress={(event) => {
: {} if ('Enter' === event.key) {
), confirmLiteralType(event);
'[literal]': {label: '', type: value.type}, }
...contextDescription.children, }}
'[key]': {label: '', type: value.type}, ref={literalTypeRef}
}} value={literalType}
onChange={(event, value) => { />
if ('.' === value || '...' === value) { )
patch({ : (
op: 'remove', <Key
path, childrenDescription={{
}); ...(
return; 'undefined' === type
} ? {'.': {label: '', type: 'undefined'}}
patch({ : {}
op: 'replace', ),
path, ...(
value: { vararg
type: 'expression', ? {'...': {label: '', type: 'undefined'}}
ops: [ : {}
{ ),
type: 'key', '[literal]': {label: '', type: value.type},
key: value, ...contextDescription.children,
}, '[key]': {label: '', type: value.type},
], }}
}, onChange={(event, value) => {
}); if ('.' === value || '...' === value) {
}} patch({
path={path} op: 'remove',
value="[literal]" path,
/> });
return;
}
patch({
op: 'replace',
path,
value: {
type: 'expression',
ops: [
{
type: 'key',
key: value,
},
],
},
});
}}
path={path}
value="[literal]"
/>
)
}
<div className="literal"> <div className="literal">
{ {
options.length > 0 options.length > 0

View File

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