@@ -429,6 +429,7 @@ type WorkspaceInteraction =
429429 | {
430430 mode : 'column' ;
431431 axis : 'x' | 'y' ;
432+ layout : 'workspace' | 'stacked' ;
432433 rowIndex : number ;
433434 index : number ;
434435 startClientX : number ;
@@ -1004,6 +1005,7 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
10041005 if ( typeof window === 'undefined' || ! window . matchMedia ) return false ;
10051006 return window . matchMedia ( STACKED_WORKSPACE_QUERY ) . matches ;
10061007 } ) ;
1008+ const [ stackedWorkspaceRatios , setStackedWorkspaceRatios ] = useState ( [ 1 , 1 ] ) ;
10071009 // Once BT panel mounts, keep it alive (preserves nodes/executor state)
10081010 const [ btEverMounted , setBtEverMounted ] = useState ( false ) ;
10091011 const [ tfEverMounted , setTfEverMounted ] = useState ( false ) ;
@@ -1089,8 +1091,7 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
10891091 [ workspaceLayout . rowSizes , workspaceTiles ]
10901092 ) ;
10911093 const renderedWorkspaceRows = useMemo (
1092- ( ) =>
1093- isWorkspaceStacked ? ( workspaceTiles . length > 0 ? [ workspaceTiles . slice ( 0 , 2 ) ] : [ ] ) : workspaceRows ,
1094+ ( ) => ( isWorkspaceStacked ? ( workspaceTiles . length > 0 ? [ workspaceTiles . slice ( 0 , 2 ) ] : [ ] ) : workspaceRows ) ,
10941095 [ isWorkspaceStacked , workspaceRows , workspaceTiles ]
10951096 ) ;
10961097 const workspaceRowRatios = useMemo (
@@ -1102,6 +1103,13 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
11021103 workspaceRows . map ( ( row , rowIndex ) => normalizeRatios ( workspaceLayout . columnRatiosByRow [ rowIndex ] , row . length ) ) ,
11031104 [ workspaceLayout . columnRatiosByRow , workspaceRows ]
11041105 ) ;
1106+ const renderedWorkspaceColumnRatiosByRow = useMemo < Record < number , number [ ] > > ( ( ) => {
1107+ if ( isWorkspaceStacked ) {
1108+ return { 0 : normalizeRatios ( stackedWorkspaceRatios , renderedWorkspaceRows [ 0 ] ?. length || 0 ) } ;
1109+ }
1110+
1111+ return Object . fromEntries ( workspaceColumnRatiosByRow . map ( ( ratios , rowIndex ) => [ rowIndex , ratios ] ) ) ;
1112+ } , [ isWorkspaceStacked , renderedWorkspaceRows , stackedWorkspaceRatios , workspaceColumnRatiosByRow ] ) ;
11051113 const capturedWorkspaceLayout = useMemo < WorkspaceLayoutState > ( ( ) => {
11061114 const rowSizes = workspaceRows . map ( row => row . length ) ;
11071115 const columnRatiosByRow = rowSizes . reduce < Record < number , number [ ] > > ( ( ratiosByRow , rowSize , rowIndex ) => {
@@ -1251,6 +1259,20 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
12511259 return ( ) => mediaQuery . removeEventListener ( 'change' , handleMediaChange ) ;
12521260 } , [ ] ) ;
12531261
1262+ useEffect ( ( ) => {
1263+ if ( ! isWorkspaceStacked ) return ;
1264+
1265+ // The mobile layout combines panels that may have belonged to different
1266+ // desktop rows. Start it at the top and notify canvas-based children only
1267+ // after that new geometry has committed.
1268+ if ( workspaceRef . current ) workspaceRef . current . scrollTop = 0 ;
1269+ workspaceInteractionRef . current = null ;
1270+ setIsWorkspaceResizing ( false ) ;
1271+
1272+ const id = window . setTimeout ( ( ) => window . dispatchEvent ( new Event ( 'resize' ) ) , 0 ) ;
1273+ return ( ) => window . clearTimeout ( id ) ;
1274+ } , [ isWorkspaceStacked ] ) ;
1275+
12541276 useEffect ( ( ) => {
12551277 if ( ! isWorkspaceTemplateMenuOpen ) return ;
12561278
@@ -1857,12 +1879,13 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
18571879 workspaceInteractionRef . current = {
18581880 mode : 'column' ,
18591881 axis,
1882+ layout : isWorkspaceStacked ? 'stacked' : 'workspace' ,
18601883 rowIndex,
18611884 index,
18621885 startClientX : event . clientX ,
18631886 startClientY : event . clientY ,
18641887 containerSize : ( axis === 'y' ? rowElement ?. clientHeight : rowElement ?. clientWidth ) || 1 ,
1865- startRatios : workspaceColumnRatiosByRow [ rowIndex ] || [ ] ,
1888+ startRatios : renderedWorkspaceColumnRatiosByRow [ rowIndex ] || [ ] ,
18661889 } ;
18671890 } ;
18681891
@@ -1881,16 +1904,23 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
18811904 return ;
18821905 }
18831906
1907+ const nextRatios = updateAdjacentRatios (
1908+ interaction . startRatios ,
1909+ interaction . index ,
1910+ interaction . axis === 'y' ? deltaY : deltaX ,
1911+ interaction . containerSize
1912+ ) ;
1913+
1914+ if ( interaction . layout === 'stacked' ) {
1915+ setStackedWorkspaceRatios ( nextRatios ) ;
1916+ return ;
1917+ }
1918+
18841919 setWorkspaceLayout ( prev => ( {
18851920 ...prev ,
18861921 columnRatiosByRow : {
18871922 ...prev . columnRatiosByRow ,
1888- [ interaction . rowIndex ] : updateAdjacentRatios (
1889- interaction . startRatios ,
1890- interaction . index ,
1891- interaction . axis === 'y' ? deltaY : deltaX ,
1892- interaction . containerSize
1893- ) ,
1923+ [ interaction . rowIndex ] : nextRatios ,
18941924 } ,
18951925 } ) ) ;
18961926 } , [ ] ) ;
@@ -3453,7 +3483,7 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
34533483 data-workspace-card-id = { tile . id }
34543484 data-workspace-row-index = { rowIndex }
34553485 data-workspace-column-index = { columnIndex }
3456- style = { { flex : workspaceColumnRatiosByRow [ rowIndex ] ?. [ columnIndex ] || 1 } }
3486+ style = { { flex : renderedWorkspaceColumnRatiosByRow [ rowIndex ] ?. [ columnIndex ] || 1 } }
34573487 >
34583488 < header
34593489 className = "workspace-card-header"
@@ -3490,7 +3520,7 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
34903520 data-workspace-card-id = { tile . id }
34913521 data-workspace-row-index = { rowIndex }
34923522 data-workspace-column-index = { columnIndex }
3493- style = { { flex : workspaceColumnRatiosByRow [ rowIndex ] ?. [ columnIndex ] || 1 } }
3523+ style = { { flex : renderedWorkspaceColumnRatiosByRow [ rowIndex ] ?. [ columnIndex ] || 1 } }
34943524 >
34953525 < header
34963526 className = "workspace-card-header"
@@ -3525,7 +3555,7 @@ const MainControlView: React.FC<MainControlViewProps> = ({ connectionParams, onD
35253555 data-workspace-card-id = { tile . panel . id }
35263556 data-workspace-row-index = { rowIndex }
35273557 data-workspace-column-index = { columnIndex }
3528- style = { { flex : workspaceColumnRatiosByRow [ rowIndex ] ?. [ columnIndex ] || 1 } }
3558+ style = { { flex : renderedWorkspaceColumnRatiosByRow [ rowIndex ] ?. [ columnIndex ] || 1 } }
35293559 onAnimationEnd = { ( ) => {
35303560 setLastAddedWorkspacePanelId ( prev => ( prev === tile . panel . id ? null : prev ) ) ;
35313561 setExecutionJumpPanelId ( prev => ( prev === tile . panel . id ? null : prev ) ) ;
0 commit comments