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 './App.css'
import { Editor, initialEditorState, type EditorState } from './Editor'
@ -82,9 +81,9 @@ const tripleFunctionCallEditorState: EditorState = {
}
export function App() {
const [history, setHistory] = useState([initialEditorState]);
// const [history, setHistory] = useState([initialEditorState]);
// const [history, setHistory] = useState([nonEmptyEditorState]);
// const [history, setHistory] = useState([tripleFunctionCallEditorState]);
const [history, setHistory] = useState([tripleFunctionCallEditorState]);
const [future, setFuture] = useState<EditorState[]>([]);

View file

@ -1,12 +1,12 @@
import { apply, getType, getInst, assignFn, UnifyError } from "dope2";
import type { Dynamic, State2Props } from "./util/extra";
import { useState } from "react";
import { apply, UnifyError } from "dope2";
import { Editor, type EditorState } from "./Editor";
import { Value } from "./Value";
import type { Dynamic, State2Props } from "./util/extra";
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<
FnState=EditorState,
@ -110,11 +110,17 @@ export function CallBlock({ state, setState, onResolve }: CallBlockProps) {
const {unifyError, setFn, setInput, onFnResolve, onInputResolve, onFnCancel, onInputCancel}
= headlessCallBlock({ state, setState, onResolve });
return <span className={"functionBlock" + (unifyError ? " unifyError" : "")}>
<FunctionHeader fn={state.fn}/>
<FunctionHeader
fn={state.fn}
setFn={setFn}
onFnResolve={onFnResolve} />
<div className="functionParams">
<div className="outputParam">
{/* 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} />
{/* Output (or Error) */}
@ -125,25 +131,39 @@ export function CallBlock({ state, setState, onResolve }: CallBlockProps) {
</span>;
}
function FunctionHeader({ fn }) {
function FunctionHeader({ fn, setFn, onFnResolve }) {
if (fn.kind === "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
// 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 {
// end of recursion - draw function name
return <div className="functionName">
&#119891;&#119899;&nbsp;
<Editor state={fn} setState={() => {/*todo*/}}
onResolve={() => {}} onCancel={() => {/*todo*/}}/>
<Editor
state={fn}
setState={setFn}
onResolve={onFnResolve}
onCancel={() => {/*todo*/}}/>
</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">
{(fn.kind === "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:
<InputParams
fn={fn.fn}
setFn={fnFn => setFn({...fn, fn: fnFn})}
input={fn.input}
setInput={() => {/*todo*/}}
onInputResolve={() => {/*todo*/}}
setInput={fnInput => setFn({...fn, input: fnInput})}
onFnResolve={onFnFnResolve}
onInputResolve={onFnInputResolve}
onInputCancel={() => {/*todo*/}}/>
}