index.tsx
Overview
This file defines React components and hooks for managing a custom context menu associated with nodes in a React Flow graph interface. It enables users to perform actions such as duplicating or deleting nodes directly from a contextual popup menu that appears on right-clicking a node.
The primary exports include:
NodeContextMenu: A visual component rendering the context menu with action buttons.useHandleNodeContextMenu: A custom React hook that manages the context menu's state and positioning logic based on user interactions.
This file leverages the useReactFlow hook from the @xyflow/react library to interact with the graph state (nodes and edges). The context menu is styled via a CSS module (index.less).
Detailed Explanations
Interface: INodeContextMenu
Defines the properties passed to the NodeContextMenu component and used to position the context menu in the viewport.
Property | Type | Description |
|---|---|---|
| Unique identifier of the node for which the menu shows. | |
|
| CSS |
|
| CSS |
|
| Optional CSS |
|
| Optional CSS bottom position for the menu. |
| Allows additional arbitrary properties. |
Component: NodeContextMenu
A functional React component that renders a context menu for a node, allowing duplication and deletion.
Props
id: string – ID of the node.
top: number– Vertical position for the menu.left: number– Horizontal position for the menu.right?: number– Optional right CSS position.bottom?: number– Optional bottom CSS position....props– Additional props forwarded to the container<div>.
Functionality
Uses useReactFlow() to access graph manipulation methods:
getNode,setNodes,addNodes, andsetEdges.Duplicate Node:
Retrieves the original node by
id.Creates a copy with:
New
idas${originalId}-copy.Position offset by +50 pixels in both x and y directions.
Same data and other properties copied.
Adds the new node to the graph.
Delete Node:
Removes the node from the
nodesarray.Removes all edges where the node is a source.
Return
JSX markup for a styled div containing:
A label showing the current node ID.
Two buttons:
Duplicate: triggers node duplication.
Delete: triggers node deletion.
Usage Example
<NodeContextMenu
id="node-1"
top={100}
left={200}
/>
This renders the context menu positioned at (top: 100px, left: 200px) for the node with ID "node-1".
Hook: useHandleNodeContextMenu(sideWidth: number)
A custom React hook to manage the state and behavior of the node context menu.
Parameters
sideWidth: number– The width of a sidebar or offset used to calculate horizontal positioning of the menu.
Returns
An object containing:
Property | Type | Description |
|---|---|---|
|
| Current state of the context menu (position & node id). |
|
| Event handler to open and position the context menu on right-click. |
|
| Event handler to close the context menu on pane clicks. |
|
| Ref for the container DOM element to calculate boundaries. |
Behavior Details
onNodeContextMenu:Prevents the default browser context menu.
Reads the bounding rect of a referenced container to avoid positioning the menu off-screen.
Calculates and sets the menu position near the mouse cursor, offset by
sideWidthhorizontally and a fixed vertical offset (144pixels).
onPaneClick:Clears the menu state, effectively closing it.
Usage Example
const sideWidth = 240; // e.g., width of sidebar
const { onNodeContextMenu, menu, onPaneClick, ref } = useHandleNodeContextMenu(sideWidth);
return (
<div ref={ref} onClick={onPaneClick}>
<ReactFlow onNodeContextMenu={onNodeContextMenu}>
{/* graph content */}
</ReactFlow>
{menu.id && (
<NodeContextMenu {...menu} />
)}
</div>
);
Important Implementation Details
Positioning Logic: The menu's position is calculated relative to the mouse event's client coordinates, adjusted by the sidebar width and a vertical offset to ensure visibility and avoid overflow.
Node Duplication: The copied node's position is shifted by 50 pixels on both axes to keep it visible and distinguishable from the original node.
Edge Cleanup on Deletion: When a node is deleted, all edges where the node is the source are also removed to maintain graph consistency.
Use of React Flow Context: The file tightly integrates with
@xyflow/react'suseReactFlowhook to mutate nodes and edges, ensuring synchronization with the overall graph state.
Interaction with Other Parts of the System
React Flow Graph: This file depends on
@xyflow/reactfor graph state management. The context menu actions directly update the shared graph state.Styling: Uses CSS modules via
index.lessto style the context menu.Parent Components: The
useHandleNodeContextMenuhook is intended to be used in a container component wrapping the React Flow canvas to handle user interactions and display the menu.Events: The context menu is triggered by right-click events (
onNodeContextMenu) on nodes rendered by the React Flow graph.
Mermaid Component Diagram
componentDiagram
component NodeContextMenu {
+duplicateNode()
+deleteNode()
+render()
}
component useHandleNodeContextMenu {
+onNodeContextMenu(event, node)
+onPaneClick()
+menu: INodeContextMenu
+ref: React.RefObject
}
NodeContextMenu <.. useHandleNodeContextMenu : uses props
useHandleNodeContextMenu --> ReactFlow : interacts via event handlers
Summary
This file provides a reusable React context menu component and corresponding hook to enable node-specific interactions (duplicate/delete) in a React Flow graph. It abstracts the complexity of positioning and state management, allowing parent components to easily integrate node context menus with minimal setup. The reliance on @xyflow/react hooks ensures seamless synchronization with the graph's internal state.