Skip to content

Commit bce0f5b

Browse files
committed
fix: freeze edge pie menu buttons during exit animation to prevent loss of state
1 parent b425ebd commit bce0f5b

1 file changed

Lines changed: 15 additions & 5 deletions

File tree

src/NodeCanvas.jsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)