@@ -53,15 +53,10 @@ import {
5353 getNodeBounds ,
5454 calculateReflowPositions ,
5555 NodeBounds ,
56- nodesOverlap
56+ snapToGrid
5757} from './utils' ;
5858import { FloatingWindow } from '../layout/FloatingWindow' ;
5959
60- export function snapToGrid ( value : number ) : number {
61- const snapped = Math . round ( value / 20 ) * 20 ;
62- return Math . max ( snapped , 0 ) ;
63- }
64-
6560export function findNodeForExit (
6661 definition : FlowDefinition ,
6762 exitUuid : string
@@ -1636,22 +1631,13 @@ export class Editor extends RapidElement {
16361631
16371632 /**
16381633 * Checks for node collisions and reflows nodes as needed.
1639- * Nodes are only moved downward to resolve collisions.
1640- *
1641- * @param movedNodeUuids - UUIDs of nodes that were just moved/dropped
1642- * @param droppedNodeUuid - UUID of the specific node that was dropped (if applicable)
1643- * @param dropTargetBounds - Bounds of the node that was dropped onto (if applicable)
1634+ * Sacred nodes (just moved/dropped) keep their positions while
1635+ * other nodes are moved in the least-disruptive direction.
16441636 */
1645- private checkCollisionsAndReflow (
1646- movedNodeUuids : string [ ] ,
1647- droppedNodeUuid : string | null = null ,
1648- dropTargetBounds : NodeBounds | null = null
1649- ) : void {
1637+ private checkCollisionsAndReflow ( sacredNodeUuids : string [ ] ) : void {
16501638 if ( ! this . definition ) return ;
16511639
1652- // Get all node bounds (only for actual nodes, not stickies)
16531640 const allBounds : NodeBounds [ ] = [ ] ;
1654-
16551641 for ( const node of this . definition . nodes ) {
16561642 const nodeUI = this . definition . _ui ?. nodes [ node . uuid ] ;
16571643 if ( ! nodeUI ?. position ) continue ;
@@ -1662,45 +1648,17 @@ export class Editor extends RapidElement {
16621648 }
16631649 }
16641650
1665- // Check if we need to determine midpoint priority for a dropped node
1666- let targetHasPriority = false ;
1667- if ( droppedNodeUuid && dropTargetBounds ) {
1668- const droppedBounds = allBounds . find ( ( b ) => b . uuid === droppedNodeUuid ) ;
1669- if ( droppedBounds ) {
1670- // Check if the bottom of the dropped node is below the midpoint of the target
1671- // If bottom is above midpoint, dropped node gets preference (targetHasPriority = false)
1672- // If bottom is below midpoint, target gets preference (targetHasPriority = true)
1673- const droppedBottom = droppedBounds . bottom ;
1674- const targetMidpoint =
1675- dropTargetBounds . top + dropTargetBounds . height / 2 ;
1676- targetHasPriority = droppedBottom > targetMidpoint ;
1677- }
1678- }
1679-
1680- // Calculate reflow positions for each moved node
1681- const allReflowPositions : { [ uuid : string ] : FlowPosition } = { } ;
1682-
1683- for ( const movedUuid of movedNodeUuids ) {
1684- const movedBounds = allBounds . find ( ( b ) => b . uuid === movedUuid ) ;
1685- if ( ! movedBounds ) continue ;
1686-
1687- // Calculate reflow for this moved node
1688- const reflowPositions = calculateReflowPositions (
1689- movedUuid ,
1690- movedBounds ,
1691- allBounds ,
1692- droppedNodeUuid === movedUuid ? targetHasPriority : false
1693- ) ;
1651+ const reflowPositions = calculateReflowPositions (
1652+ sacredNodeUuids ,
1653+ allBounds
1654+ ) ;
16941655
1695- // Merge into all reflow positions
1656+ if ( reflowPositions . size > 0 ) {
1657+ const positions : { [ uuid : string ] : FlowPosition } = { } ;
16961658 for ( const [ uuid , position ] of reflowPositions . entries ( ) ) {
1697- allReflowPositions [ uuid ] = position ;
1659+ positions [ uuid ] = position ;
16981660 }
1699- }
1700-
1701- // If there are positions to update, apply them
1702- if ( Object . keys ( allReflowPositions ) . length > 0 ) {
1703- getStore ( ) . getState ( ) . updateCanvasPositions ( allReflowPositions ) ;
1661+ getStore ( ) . getState ( ) . updateCanvasPositions ( positions ) ;
17041662 }
17051663 }
17061664
@@ -1905,49 +1863,7 @@ export class Editor extends RapidElement {
19051863 if ( nodeUuids . length > 0 ) {
19061864 // Allow DOM to update before checking collisions
19071865 setTimeout ( ( ) => {
1908- // If only one node was moved, detect which node it might have been dropped onto
1909- let droppedNodeUuid : string | null = null ;
1910- let dropTargetBounds : NodeBounds | null = null ;
1911-
1912- if ( nodeUuids . length === 1 ) {
1913- droppedNodeUuid = nodeUuids [ 0 ] ;
1914- const droppedNodeUI = this . definition . _ui ?. nodes [ droppedNodeUuid ] ;
1915-
1916- if ( droppedNodeUI ?. position ) {
1917- const droppedBounds = getNodeBounds (
1918- droppedNodeUuid ,
1919- droppedNodeUI . position
1920- ) ;
1921-
1922- if ( droppedBounds ) {
1923- // Find which node (if any) the dropped node overlaps with
1924- for ( const node of this . definition . nodes ) {
1925- if ( node . uuid === droppedNodeUuid ) continue ;
1926-
1927- const nodeUI = this . definition . _ui ?. nodes [ node . uuid ] ;
1928- if ( ! nodeUI ?. position ) continue ;
1929-
1930- const targetBounds = getNodeBounds (
1931- node . uuid ,
1932- nodeUI . position
1933- ) ;
1934- if (
1935- targetBounds &&
1936- nodesOverlap ( droppedBounds , targetBounds )
1937- ) {
1938- dropTargetBounds = targetBounds ;
1939- break ; // Use the first overlapping node
1940- }
1941- }
1942- }
1943- }
1944- }
1945-
1946- this . checkCollisionsAndReflow (
1947- nodeUuids ,
1948- droppedNodeUuid ,
1949- dropTargetBounds
1950- ) ;
1866+ this . checkCollisionsAndReflow ( nodeUuids ) ;
19511867 } , 0 ) ;
19521868 } else {
19531869 // No nodes moved, just repaint connections
0 commit comments