@@ -18,6 +18,7 @@ import { useShallow } from 'zustand/react/shallow'
1818import type { OAuthConnectEventDetail } from '@/lib/copilot/tools/client/other/oauth-request-access'
1919import { createLogger } from '@/lib/logs/console/logger'
2020import type { OAuthProvider } from '@/lib/oauth'
21+ import { BLOCK_DIMENSIONS , CONTAINER_DIMENSIONS } from '@/lib/workflows/blocks/block-dimensions'
2122import { TriggerUtils } from '@/lib/workflows/triggers/triggers'
2223import { useWorkspacePermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
2324import {
@@ -1501,6 +1502,77 @@ const WorkflowContent = React.memo(() => {
15011502 // Only sync non-position changes (like selection) to store if needed
15021503 } , [ ] )
15031504
1505+ /**
1506+ * Updates container dimensions in displayNodes during drag.
1507+ * This allows live resizing of containers as their children are dragged.
1508+ */
1509+ const updateContainerDimensionsDuringDrag = useCallback (
1510+ ( draggedNodeId : string , draggedNodePosition : { x : number ; y : number } ) => {
1511+ const parentId = blocks [ draggedNodeId ] ?. data ?. parentId
1512+ if ( ! parentId ) return
1513+
1514+ setDisplayNodes ( ( currentNodes ) => {
1515+ // Find all children of this container from current displayNodes
1516+ const childNodes = currentNodes . filter ( ( n ) => n . parentId === parentId )
1517+ if ( childNodes . length === 0 ) return currentNodes
1518+
1519+ // Calculate dimensions using current positions from displayNodes
1520+ // Match padding values from use-node-utilities.ts calculateLoopDimensions
1521+ const headerHeight = 50
1522+ const leftPadding = 16
1523+ const rightPadding = 80
1524+ const topPadding = 16
1525+ const bottomPadding = 16
1526+ const minWidth = CONTAINER_DIMENSIONS . DEFAULT_WIDTH
1527+ const minHeight = CONTAINER_DIMENSIONS . DEFAULT_HEIGHT
1528+
1529+ let maxRight = 0
1530+ let maxBottom = 0
1531+
1532+ childNodes . forEach ( ( node ) => {
1533+ // Use the dragged node's live position, others from displayNodes
1534+ const nodePosition = node . id === draggedNodeId ? draggedNodePosition : node . position
1535+
1536+ // Get dimensions - use block store for height estimates
1537+ const blockData = blocks [ node . id ]
1538+ const nodeWidth = BLOCK_DIMENSIONS . FIXED_WIDTH
1539+ const nodeHeight = blockData ?. height || node . height || BLOCK_DIMENSIONS . MIN_HEIGHT
1540+
1541+ const rightEdge = nodePosition . x + nodeWidth
1542+ const bottomEdge = nodePosition . y + nodeHeight
1543+
1544+ maxRight = Math . max ( maxRight , rightEdge )
1545+ maxBottom = Math . max ( maxBottom , bottomEdge )
1546+ } )
1547+
1548+ const newWidth = Math . max ( minWidth , leftPadding + maxRight + rightPadding )
1549+ const newHeight = Math . max ( minHeight , headerHeight + topPadding + maxBottom + bottomPadding )
1550+
1551+ // Update the container node's dimensions in displayNodes
1552+ return currentNodes . map ( ( node ) => {
1553+ if ( node . id === parentId ) {
1554+ const currentWidth = node . data ?. width || CONTAINER_DIMENSIONS . DEFAULT_WIDTH
1555+ const currentHeight = node . data ?. height || CONTAINER_DIMENSIONS . DEFAULT_HEIGHT
1556+
1557+ // Only update if dimensions changed
1558+ if ( newWidth !== currentWidth || newHeight !== currentHeight ) {
1559+ return {
1560+ ...node ,
1561+ data : {
1562+ ...node . data ,
1563+ width : newWidth ,
1564+ height : newHeight ,
1565+ } ,
1566+ }
1567+ }
1568+ }
1569+ return node
1570+ } )
1571+ } )
1572+ } ,
1573+ [ blocks ]
1574+ )
1575+
15041576 /**
15051577 * Effect to resize loops when nodes change (add/remove/position change).
15061578 * Runs on structural changes only - not during drag (position-only changes).
@@ -1681,6 +1753,11 @@ const WorkflowContent = React.memo(() => {
16811753 // Get the current parent ID of the node being dragged
16821754 const currentParentId = blocks [ node . id ] ?. data ?. parentId || null
16831755
1756+ // If the node is inside a container, update container dimensions during drag
1757+ if ( currentParentId ) {
1758+ updateContainerDimensionsDuringDrag ( node . id , node . position )
1759+ }
1760+
16841761 // Check if this is a starter block - starter blocks should never be in containers
16851762 const isStarterBlock = node . data ?. type === 'starter'
16861763 if ( isStarterBlock ) {
@@ -1812,7 +1889,14 @@ const WorkflowContent = React.memo(() => {
18121889 }
18131890 }
18141891 } ,
1815- [ getNodes , potentialParentId , blocks , getNodeAbsolutePosition , getNodeDepth ]
1892+ [
1893+ getNodes ,
1894+ potentialParentId ,
1895+ blocks ,
1896+ getNodeAbsolutePosition ,
1897+ getNodeDepth ,
1898+ updateContainerDimensionsDuringDrag ,
1899+ ]
18161900 )
18171901
18181902 /** Captures initial parent ID and position when drag starts. */
0 commit comments