better looking active states + always scroll to latest event

This commit is contained in:
Joeri Exelmans 2025-10-18 16:39:57 +02:00
parent 12e211f358
commit f80086727c
3 changed files with 27 additions and 9 deletions

View file

@ -1,4 +1,4 @@
import { useEffect, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { emptyStatechart, Statechart } from "../statecharts/abstract_syntax"; import { emptyStatechart, Statechart } from "../statecharts/abstract_syntax";
import { handleInputEvent, initialize } from "../statecharts/interpreter"; import { handleInputEvent, initialize } from "../statecharts/interpreter";
@ -28,6 +28,8 @@ export function App() {
const [time, setTime] = useState<TimeMode>({kind: "paused", simtime: 0}); const [time, setTime] = useState<TimeMode>({kind: "paused", simtime: 0});
const refRightSideBar = useRef<HTMLDivElement>(null);
function onInit() { function onInit() {
const config = initialize(ast); const config = initialize(ast);
setRT([{inputEvent: null, simtime: 0, ...config}]); setRT([{inputEvent: null, simtime: 0, ...config}]);
@ -52,7 +54,18 @@ export function App() {
function appendNewConfig(inputEvent: string, simtime: number, config: BigStepOutput) { function appendNewConfig(inputEvent: string, simtime: number, config: BigStepOutput) {
setRT([...rt.slice(0, rtIdx!+1), {inputEvent, simtime, ...config}]); setRT([...rt.slice(0, rtIdx!+1), {inputEvent, simtime, ...config}]);
setRTIdx(rtIdx!+1); setRTIdx(rtIdx!+1);
console.log('new config:', config); // console.log('new config:', config);
if (refRightSideBar.current) {
const el = refRightSideBar.current;
// console.log('scrolling to', el.scrollHeight);
console.log('scrolling to:', el);
setTimeout(() => {
el.scrollIntoView({block: "end", behavior: "smooth"});
}, 100);
// el.scrollTo(0, el.scrollHeight+1000);
}
} }
useEffect(() => { useEffect(() => {
@ -125,7 +138,9 @@ export function App() {
}}> }}>
<ShowAST {...{...ast, rt: rt.at(rtIdx!)}}/> <ShowAST {...{...ast, rt: rt.at(rtIdx!)}}/>
<br/> <br/>
<RTHistory {...{ast, rt, rtIdx, setTime, setRTIdx}}/> <div ref={refRightSideBar}>
<RTHistory {...{ast, rt, rtIdx, setTime, setRTIdx, refRightSideBar}}/>
</div>
</Box> </Box>
</Stack> </Stack>
<Box> <Box>

View file

@ -13,7 +13,7 @@
} }
.svgCanvas.active { .svgCanvas.active {
background-color: rgb(255, 140, 0, 0.2); /* background-color: rgb(255, 140, 0, 0.2); */
} }
.svgCanvas text { .svgCanvas text {
@ -42,9 +42,12 @@
stroke: rgb(230,0,0); stroke: rgb(230,0,0);
} }
.rountangle.active { .rountangle.active {
fill: darkorange; /* fill: rgb(255, 140, 0); */
fill-opacity: 0.2; /* fill-opacity: 0.2; */
stroke-width: 3px; /* stroke: rgb(100, 149, 237); */
/* stroke: */
filter: drop-shadow( 0px 0px 6px rgba(0, 150, 255, 0.8));
/* stroke-width: 3px; */
} }
.selected:hover:not(:active) { .selected:hover:not(:active) {

View file

@ -119,7 +119,7 @@ export function enterDefault(simtime: number, state: ConcreteState, rt: ActionSc
({enteredStates: enteredChildren, ...actionScope} = enterDefault(simtime, state.initial[0][1], actionScope)); ({enteredStates: enteredChildren, ...actionScope} = enterDefault(simtime, state.initial[0][1], actionScope));
enteredStates = enteredStates.union(enteredChildren); enteredStates = enteredStates.union(enteredChildren);
} }
console.warn(state.uid + ': no initial state'); // console.warn(state.uid + ': no initial state');
} }
return {enteredStates, ...actionScope}; return {enteredStates, ...actionScope};
@ -328,7 +328,7 @@ export function fireSecondHalfOfTransition(simtime: number, t: Transition, ts: M
} }
} }
} }
throw new Error("stuck in pseudo-state!!") throw new Error("stuck in pseudo-state!!");
} }
else { else {
const tgtPath = computePath({ancestor: arena, descendant: t.tgt}); const tgtPath = computePath({ancestor: arena, descendant: t.tgt});