@@ -3997,7 +3997,8 @@ function NodeCanvas() {
39973997 const [connectionControlPanelShouldShow, setConnectionControlPanelShouldShow] = useState(false);
39983998 const [edgePieMenuVisible, setEdgePieMenuVisible] = useState(false);
39993999 const [edgePieMenuRendered, setEdgePieMenuRendered] = useState(false);
4000- const edgePieMenuAnchorRef = useRef(null); // frozen on show, held through exit animation
4000+ const edgePieMenuAnchorRef = useRef(null); // frozen on show, held through exit animation
4001+ const edgePieMenuButtonsRef = useRef(null); // frozen on show, held through exit animation
40014002
40024003 // Pending swap operation state
40034004 const [pendingSwapOperation, setPendingSwapOperation] = useState(null);
@@ -9034,6 +9035,13 @@ function NodeCanvas() {
90349035 return buttons;
90359036 }, [selectedEdgeId, edgesMap, nodePrototypesMap, wizardEnabled, storeActions, startHurtleAnimationFromPanel, openWizardWithPrompt, rightPanelExpanded]);
90369037
9038+ // Freeze edge pie menu buttons when visible so they survive edge deselection during exit animation
9039+ useEffect(() => {
9040+ if (edgePieMenuVisible && edgePieMenuButtons.length > 0) {
9041+ edgePieMenuButtonsRef.current = edgePieMenuButtons;
9042+ }
9043+ }, [edgePieMenuVisible, edgePieMenuButtons]);
9044+
90379045 // Callback for activating semantic orbit from control panel
90389046 const activateSemanticOrbit = useCallback(() => {
90399047 setSemanticOrbitActive(true);
@@ -14050,7 +14058,8 @@ function NodeCanvas() {
1405014058 {/* Edge pie menu — rendered inline at the edge midpoint */}
1405114059 {(() => {
1405214060 const anchor = edgePieMenuAnchorRef.current;
14053- if (!edgePieMenuRendered || !anchor || edgePieMenuButtons.length === 0) return null;
14061+ const frozenButtons = edgePieMenuButtonsRef.current;
14062+ if (!edgePieMenuRendered || !anchor || !frozenButtons || frozenButtons.length === 0) return null;
1405414063
1405514064 // Space check: does the full button row fit on screen?
1405614065 // Use correct canvas→screen conversion: (canvasX - offsetX) * zoom + pan + rectLeft
@@ -14061,7 +14070,7 @@ function NodeCanvas() {
1406114070 const screenX = rect
1406214071 ? (anchor.x - canvasSize.offsetX) * zoom + pan.x + rect.left
1406314072 : window.innerWidth / 2;
14064- const n = edgePieMenuButtons .length;
14073+ const n = frozenButtons .length;
1406514074 // Full row extent: center ± half of ((n-1)*step + bubbleSize)
1406614075 const halfRowPx = ((n - 1) * BUBBLE_STEP / 2 + 30) * zoom;
1406714076 const isCompact = rect
@@ -14075,7 +14084,7 @@ function NodeCanvas() {
1407514084 label: 'More',
1407614085 icon: MoreHorizontal,
1407714086 action: (_id, buttonPosition) => {
14078- const menuOptions = edgePieMenuButtons .map(btn => ({
14087+ const menuOptions = frozenButtons .map(btn => ({
1407914088 label: btn.label,
1408014089 icon: btn.icon ? React.createElement(btn.icon, { size: 16, color: 'maroon' }) : null,
1408114090 action: () => btn.action(null, null),
@@ -14087,7 +14096,7 @@ function NodeCanvas() {
1408714096 );
1408814097 },
1408914098 }]
14090- : edgePieMenuButtons ;
14099+ : frozenButtons ;
1409114100
1409214101 return (
1409314102 <PieMenu
@@ -14098,6 +14107,7 @@ function NodeCanvas() {
1409814107 onHoverChange={handlePieMenuHoverChange}
1409914108 onExitAnimationComplete={() => {
1410014109 edgePieMenuAnchorRef.current = null;
14110+ edgePieMenuButtonsRef.current = null;
1410114111 setEdgePieMenuRendered(false);
1410214112 }}
1410314113 />
0 commit comments