index.tsx
Overview
This file defines a React component and a custom hook that together implement a contextual menu for nodes within a flowchart or graph interface using the @xyflow/react library. The context menu allows users to perform node-specific actions such as duplicating and deleting nodes. The hook useHandleNodeContextMenu manages the state and positioning of the context menu when a user right-clicks on a node.
In summary, this file enhances node interaction within a React Flow environment by providing a convenient in-place menu for node operations, improving user experience in graph manipulation scenarios.
Exports
interface INodeContextMenu
Describes the properties related to the node context menu positioning and identification.
Property | Type | Description |
|---|---|---|
|
| The unique identifier of the node for which the menu is shown |
|
| The vertical position (in pixels) where the menu should appear |
|
| The horizontal position (in pixels) where the menu should appear |
|
| Optional right offset for positioning the menu |
|
| Optional bottom offset for positioning the menu |
|
| Additional arbitrary properties |
NodeContextMenu Component
A React functional component that renders a context menu for a specific node in the flow.
Signature
function NodeContextMenu(props: INodeContextMenu): JSX.Element
Props
id(string): Node identifier.top(number): CSStopposition of the menu.left(number): CSSleftposition of the menu.right?(number): Optional CSSrightposition.bottom?(number): Optional CSSbottomposition....props: Additional props passed to the root<div>.
Description
Uses React Flow's hooks (
useReactFlow) to access node and edge management functions.Provides two main actions via buttons:
Duplicate: Creates a copy of the selected node at an offset position (+50px right and down).
Delete: Removes the node and all edges originating from it.
Positions itself absolutely based on the passed
top,left,right, andbottomvalues.Styled using CSS modules (
index.less).
Usage Example
<NodeContextMenu
id="node-1"
top={100}
left={200}
/>
This renders the menu at position (100px from top, 200px from left) for the node with id "node-1".
useHandleNodeContextMenu Hook
A custom React hook (marked as deprecated) that manages the state and interaction logic for showing the node context menu on right-click.
Signature
function useHandleNodeContextMenu(sideWidth: number): {
onNodeContextMenu: NodeMouseHandler,
menu: INodeContextMenu,
onPaneClick: () => void,
ref: React.RefObject<any>
}
Parameters
sideWidth(number): A width offset used to calculate the horizontal position of the menu.
Returns
onNodeContextMenu: Event handler to be attached to node context menu events (right-click). Prevents native context menu and calculates custom menu position.menu: Current menu state (INodeContextMenu), including position and node id.onPaneClick: Handler to close the context menu when clicking outside.ref: A React ref to the container element used to compute bounds for positioning.
Description
Listens for right-click events on nodes.
Computes menu position based on mouse event coordinates minus fixed offsets, ensuring the menu is placed near the clicked node but accounting for UI constraints like sidebar width.
Contains commented-out logic for boundary detection to keep the menu inside visible viewport, which can be re-enabled if needed.
Provides a
refto be attached to the container pane to measure its dimensions.Clears the menu when the pane is clicked elsewhere.
Usage Example
const sideWidth = 200;
const { onNodeContextMenu, menu, onPaneClick, ref } = useHandleNodeContextMenu(sideWidth);
// In render:
<div ref={ref} onClick={onPaneClick}>
<ReactFlow onNodeContextMenu={onNodeContextMenu}>
{/* flow nodes and edges */}
{menu.id && (
<NodeContextMenu {...menu} />
)}
</ReactFlow>
</div>
Important Implementation Details
Position Calculation for Menu: The menu position is computed relative to mouse event coordinates offset by constants (e.g., 144px vertically and
sideWidthhorizontally) to account for UI layout such as sidebars or headers.Node Duplication Logic: When duplicating a node, the new node is positioned offset by +50 pixels on both X and Y axes relative to the original node’s position. The copied node id is suffixed with
-copyto avoid conflicts.Node Deletion Logic: Deletes the node and also removes all edges where the deleted node is the source. This ensures graph consistency.
Deprecated Hook: The
useHandleNodeContextMenuhook is marked@deprecated, suggesting that this hook might be replaced or refactored in future versions.Styling: The component uses CSS modules (
index.less) for styling the context menu, ensuring styles are scoped locally.
Interaction with Other Parts of the System
@xyflow/react Integration: Uses
useReactFlowhook from@xyflow/reactto manipulate the graph's nodes and edges programmatically.React Flow UI: Designed to be used within a React Flow environment where nodes and edges represent a flowchart or graph structure.
Styling: Relies on an external stylesheet (
index.less) for styling the menu.Event Handling: The hook and component expect to be integrated with React Flow's event system, particularly the node context menu event.
File Structure and Workflow Diagram
componentDiagram
component "NodeContextMenu" as NCM
component "useHandleNodeContextMenu Hook" as Hook
component "React Flow Graph" as RFG
component "CSS Module (index.less)" as CSS
Hook <..> NCM : provides menu state & handlers
NCM --> RFG : uses useReactFlow API
Hook --> RFG : sets event handlers (onNodeContextMenu)
NCM --> CSS : styled by
Summary
This file is a React component and hook module that implements a node-specific context menu within a React Flow graph UI. It allows users to duplicate or delete nodes interactively through a contextual popup menu positioned near the user's click. The hook manages menu state and positioning logic, while the component renders the menu and invokes node operations through the React Flow API. This enhances node manipulation UX in flowchart or graph-based applications built with @xyflow/react.
If you require further details or integration guidance, please let me know!