implement nested handlers in call block

This commit is contained in:
Joeri Exelmans 2025-05-12 17:18:57 +02:00
parent 1f831b0517
commit 9afaa41fbb
2 changed files with 39 additions and 18 deletions

View file

@ -1,4 +1,3 @@
// import { useState } from 'react'
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import './App.css' import './App.css'
import { Editor, initialEditorState, type EditorState } from './Editor' import { Editor, initialEditorState, type EditorState } from './Editor'
@ -82,9 +81,9 @@ const tripleFunctionCallEditorState: EditorState = {
} }
export function App() { export function App() {
const [history, setHistory] = useState([initialEditorState]); // const [history, setHistory] = useState([initialEditorState]);
// const [history, setHistory] = useState([nonEmptyEditorState]); // const [history, setHistory] = useState([nonEmptyEditorState]);
// const [history, setHistory] = useState([tripleFunctionCallEditorState]); const [history, setHistory] = useState([tripleFunctionCallEditorState]);
const [future, setFuture] = useState<EditorState[]>([]); const [future, setFuture] = useState<EditorState[]>([]);

View file

@ -1,12 +1,12 @@
import { apply, getType, getInst, assignFn, UnifyError } from "dope2"; import { useState } from "react";
import type { Dynamic, State2Props } from "./util/extra";
import { apply, UnifyError } from "dope2";
import { Editor, type EditorState } from "./Editor"; import { Editor, type EditorState } from "./Editor";
import { Value } from "./Value";
import type { Dynamic, State2Props } from "./util/extra";
import "./CallBlock.css"; import "./CallBlock.css";
import { useEffect, useState } from "react";
import { Type } from "./Type";
import { Value } from "./Value";
import { focusPrevElement } from "./util/dom_trickery";
export interface CallBlockState< export interface CallBlockState<
FnState=EditorState, FnState=EditorState,
@ -110,11 +110,17 @@ export function CallBlock({ state, setState, onResolve }: CallBlockProps) {
const {unifyError, setFn, setInput, onFnResolve, onInputResolve, onFnCancel, onInputCancel} const {unifyError, setFn, setInput, onFnResolve, onInputResolve, onFnCancel, onInputCancel}
= headlessCallBlock({ state, setState, onResolve }); = headlessCallBlock({ state, setState, onResolve });
return <span className={"functionBlock" + (unifyError ? " unifyError" : "")}> return <span className={"functionBlock" + (unifyError ? " unifyError" : "")}>
<FunctionHeader fn={state.fn}/> <FunctionHeader
fn={state.fn}
setFn={setFn}
onFnResolve={onFnResolve} />
<div className="functionParams"> <div className="functionParams">
<div className="outputParam"> <div className="outputParam">
{/* Sequence of input parameters */} {/* Sequence of input parameters */}
<InputParams fn={state.fn} input={state.input} setInput={setInput} <InputParams
fn={state.fn} setFn={setFn}
input={state.input} setInput={setInput}
onFnResolve={onFnResolve}
onInputResolve={onInputResolve} onInputCancel={onInputCancel} /> onInputResolve={onInputResolve} onInputCancel={onInputCancel} />
{/* Output (or Error) */} {/* Output (or Error) */}
@ -125,25 +131,39 @@ export function CallBlock({ state, setState, onResolve }: CallBlockProps) {
</span>; </span>;
} }
function FunctionHeader({ fn }) { function FunctionHeader({ fn, setFn, onFnResolve }) {
if (fn.kind === "call") { if (fn.kind === "call") {
// if the function we're calling is itself the result of a function call, // if the function we're calling is itself the result of a function call,
// then we are anonymous, and so we don't draw a function name // then we are anonymous, and so we don't draw a function name
// recurse: // recurse:
return <FunctionHeader fn={fn.fn} />; const {
onFnResolve : onFnFnResolve
} = headlessCallBlock({state: fn, setState: setFn, onResolve: onFnResolve});
return <FunctionHeader
fn={fn.fn}
setFn={fnFn => setFn({...fn, fn: fnFn})}
onFnResolve={onFnFnResolve} />;
} }
else { else {
// end of recursion - draw function name // end of recursion - draw function name
return <div className="functionName"> return <div className="functionName">
&#119891;&#119899;&nbsp; &#119891;&#119899;&nbsp;
<Editor state={fn} setState={() => {/*todo*/}} <Editor
onResolve={() => {}} onCancel={() => {/*todo*/}}/> state={fn}
setState={setFn}
onResolve={onFnResolve}
onCancel={() => {/*todo*/}}/>
</div>; </div>;
} }
} }
function InputParams({ fn, input, setInput, onInputResolve, onInputCancel }) { function InputParams({ fn, setFn, input, setInput, onFnResolve, onInputResolve, onInputCancel }) {
const {
onInputResolve: onFnInputResolve,
onFnResolve : onFnFnResolve
} = headlessCallBlock({state: fn, setState: setFn, onResolve: onFnResolve});
return <div className="inputParam"> return <div className="inputParam">
{(fn.kind === "call") && {(fn.kind === "call") &&
// if the function we're calling is itself the result of a function call, // if the function we're calling is itself the result of a function call,
@ -152,9 +172,11 @@ function InputParams({ fn, input, setInput, onInputResolve, onInputCancel }) {
// Input(s) of the function we're calling: // Input(s) of the function we're calling:
<InputParams <InputParams
fn={fn.fn} fn={fn.fn}
setFn={fnFn => setFn({...fn, fn: fnFn})}
input={fn.input} input={fn.input}
setInput={() => {/*todo*/}} setInput={fnInput => setFn({...fn, input: fnInput})}
onInputResolve={() => {/*todo*/}} onFnResolve={onFnFnResolve}
onInputResolve={onFnInputResolve}
onInputCancel={() => {/*todo*/}}/> onInputCancel={() => {/*todo*/}}/>
} }