11import { Box } from "@mui/material" ;
22import { useSelector } from "@xstate/react" ;
3- import React , {
4- useCallback ,
5- useEffect ,
6- useLayoutEffect ,
7- useMemo ,
8- useRef ,
9- useState ,
10- } from "react" ;
3+ import React , { useCallback , useEffect , useRef , useState } from "react" ;
114import { colors } from "theme/tokens/variables" ;
12- import { FEATURES , featureFlags , logger } from "utils" ;
5+ import { FEATURES , featureFlags } from "utils" ;
136import { ActorRef , EventObject , State } from "xstate" ;
147import ErrorInspector from "../errorInspector/ErrorInspector" ;
158import {
169 DefinitionMachineContext ,
1710 DefinitionMachineEventTypes ,
1811 WorkflowDefinitionEvents ,
1912} from "../state/types" ;
20- import { AssistantPanel , SHRINKED_HEIGHT } from "./AssistantPanel" ;
13+ import { AssistantPanel } from "./AssistantPanel" ;
2114import { ConfirmationDialogs } from "./ConfirmationDialogs" ;
2215import { EditorTabs } from "./EditorTabs" ;
2316import { TabContent } from "./TabContent" ;
@@ -109,6 +102,7 @@ const EditorPanel = ({ definitionActor }: EditorPanelProps) => {
109102 } | null > ( null ) ;
110103 const shouldHandleClickRef = useRef < { wasCollapsed : boolean } | null > ( null ) ;
111104 const editorPanelContainerRef = useRef < HTMLDivElement > ( null ) ;
105+ const isMountedRef = useRef ( false ) ;
112106
113107 // Handle document-level mouse events during resize
114108 // Note: We use refs (wasCollapsed) instead of XState state (isAgentExpanded) during drag
@@ -197,18 +191,19 @@ const EditorPanel = ({ definitionActor }: EditorPanelProps) => {
197191 } , [ isResizing , handleMouseMove , handleMouseUp ] ) ;
198192
199193 useEffect ( ( ) => {
200- if ( ! tabsContainerRef . current ) return ;
201-
202- const updateTabsHeight = ( ) => {
203- if ( tabsContainerRef . current ) {
204- const height = tabsContainerRef . current . offsetHeight || 48 ;
205- setTabsHeight ( ( prev ) => ( prev !== height ? height : prev ) ) ;
206- }
207- } ;
194+ const el = tabsContainerRef . current ;
195+ if ( ! el ) return ;
196+
197+ const resizeObserver = new ResizeObserver ( ( entries ) => {
198+ const height =
199+ entries [ 0 ] ?. borderBoxSize ?. [ 0 ] ?. blockSize ??
200+ entries [ 0 ] ?. contentRect ?. height ??
201+ el . offsetHeight ??
202+ 48 ;
203+ setTabsHeight ( ( prev ) => ( prev !== height ? height : prev ) ) ;
204+ } ) ;
208205
209- updateTabsHeight ( ) ;
210- const resizeObserver = new ResizeObserver ( updateTabsHeight ) ;
211- resizeObserver . observe ( tabsContainerRef . current ) ;
206+ resizeObserver . observe ( el ) ;
212207
213208 return ( ) => {
214209 resizeObserver . disconnect ( ) ;
@@ -227,8 +222,6 @@ const EditorPanel = ({ definitionActor }: EditorPanelProps) => {
227222 ) ;
228223 } ;
229224
230- logger . debug ( "Rendering Editor Panel" ) ;
231-
232225 const handleResetConfirmation = ( val : boolean ) =>
233226 ( val ? handleConfirmReset : handleCancelRequest ) ( ) ;
234227
@@ -249,24 +242,23 @@ const EditorPanel = ({ definitionActor }: EditorPanelProps) => {
249242 state . context . errorInspectorMachine ,
250243 ) ;
251244
252- // When auto-expanded (e.g. new workflow) with no height set, measure container and set full height
253- useLayoutEffect ( ( ) => {
254- if ( ! isAgentExpanded || agentPanelHeight !== null ) return ;
255- if ( ! editorPanelContainerRef . current ) return ;
256- const containerRect =
257- editorPanelContainerRef . current . getBoundingClientRect ( ) ;
258- const maxHeight =
259- containerRect . height - tabsHeight - ( errorInspectorActor ? 50 : 0 ) ;
260- if ( maxHeight > 0 ) setAgentPanelHeight ( maxHeight ) ;
261- } , [ isAgentExpanded , agentPanelHeight , tabsHeight , errorInspectorActor ] ) ;
262-
263- // Effective height: use measured value when expanded, or explicit agentPanelHeight
264- const effectiveAgentPanelHeight = useMemo ( ( ) => {
265- if ( isAgentExpanded && agentPanelHeight === null ) {
266- return SHRINKED_HEIGHT ;
245+ // Persist expanded state so it survives navigation to a new workflow
246+ useEffect ( ( ) => {
247+ localStorage . setItem ( "agentExpanded" , String ( isAgentExpanded ) ) ;
248+ } , [ isAgentExpanded ] ) ;
249+
250+ // Reset height when navigating to a different workflow so the layout effect re-measures.
251+ // Skip on initial mount — agentPanelHeight is already null and the layout effect below
252+ // has already run (effects execute after layout effects, so resetting here would undo it).
253+ useEffect ( ( ) => {
254+ if ( ! isMountedRef . current ) {
255+ isMountedRef . current = true ;
256+ return ;
267257 }
268- return agentPanelHeight ;
269- } , [ isAgentExpanded , agentPanelHeight ] ) ;
258+ setAgentPanelHeight ( null ) ;
259+ } , [ definitionActor ] ) ;
260+
261+ const effectiveAgentPanelHeight = agentPanelHeight ;
270262
271263 // Calculate available height for tab content (accounting for error inspector and assistant panel)
272264 const getTabContentHeight = useCallback ( ( ) => {
@@ -299,41 +291,16 @@ const EditorPanel = ({ definitionActor }: EditorPanelProps) => {
299291
300292 // When collapsed, start with collapsed height (50px)
301293 // When expanded, use current height or maxHeight
302- const startHeight = isAgentExpanded ? agentPanelHeight || maxHeight : 50 ; // Collapsed height
303-
304- // If starting from collapsed, calculate initial height based on mouse position
305- // This prevents the panel from using calc() value when it expands
306- if ( ! isAgentExpanded && agentPanelHeight === null ) {
307- // Calculate height based on distance from bottom of container
308- // Mouse Y position relative to container bottom
309- const mouseYFromBottom = containerRect . bottom - e . clientY ;
310- // Initial height is the distance from bottom, clamped between min and max
311- const initialHeight = Math . max (
312- 200 ,
313- Math . min ( maxHeight , mouseYFromBottom ) ,
314- ) ;
315- // Set height immediately so it's available when panel expands
316- setAgentPanelHeight ( initialHeight ) ;
317- // Store resize state with collapsed height as start point
318- resizeStateRef . current = {
319- startY : e . clientY ,
320- startHeight : 50 , // Use 50px (collapsed height) as starting point for drag calculations
321- maxHeight,
322- containerRect,
323- wasCollapsed : true ,
324- hasExpanded : false ,
325- } ;
326- } else {
327- // Store resize state in refs for the useEffect to use
328- resizeStateRef . current = {
329- startY : e . clientY ,
330- startHeight,
331- maxHeight,
332- containerRect,
333- wasCollapsed : ! isAgentExpanded ,
334- hasExpanded : false ,
335- } ;
336- }
294+ const startHeight = isAgentExpanded ? agentPanelHeight || maxHeight : 50 ;
295+
296+ resizeStateRef . current = {
297+ startY : e . clientY ,
298+ startHeight,
299+ maxHeight,
300+ containerRect,
301+ wasCollapsed : ! isAgentExpanded ,
302+ hasExpanded : false ,
303+ } ;
337304
338305 resizeStartRef . current = { x : e . clientX , y : e . clientY } ;
339306 isResizingRef . current = false ;
@@ -402,10 +369,6 @@ const EditorPanel = ({ definitionActor }: EditorPanelProps) => {
402369 setAgentPanelHeight ( maxHeight ) ;
403370 } , [ tabsHeight , errorInspectorActor ] ) ;
404371
405- const handleHeightChange = useCallback ( ( height : number ) => {
406- setAgentPanelHeight ( height ) ;
407- } , [ ] ) ;
408-
409372 return (
410373 < >
411374 { isResizing && (
@@ -489,7 +452,6 @@ const EditorPanel = ({ definitionActor }: EditorPanelProps) => {
489452 onHeaderClick = { handleHeaderClick }
490453 onToggleExpanded = { handleToggleExpanded }
491454 onMaximize = { handleMaximize }
492- onHeightChange = { handleHeightChange }
493455 isResizing = { isResizing }
494456 />
495457 ) }
0 commit comments