index.tsx
Overview
This file implements a React component and a custom hook related to managing a context menu for nodes within a flow diagram or graph interface, leveraging the @xyflow/react library. The primary goal is to provide UI controls—specifically a context menu that appears on right-clicking a node—enabling users to duplicate or delete nodes interactively.
Key functionalities include:
Rendering a customizable context menu positioned relative to a node.
Duplicating a node with an offset position.
Deleting a node and its connected edges.
Managing the context menu's open/close state and positioning via a custom hook.
This file is typically integrated within a React Flow environment where nodes represent interactive elements in a visual workflow or graph.
Exports
Interface: INodeContextMenu
export interface INodeContextMenu {
id: string;
top: number;
left: number;
right?: number;
bottom?: number;
[key: string]: unknown;
}
Description
Defines the properties expected by the NodeContextMenu component, specifying the node ID and positioning coordinates to place the context menu relative to the node.
Properties
Property | Type | Description |
|---|---|---|
id | string | The unique identifier of the node for which the menu is shown. |
top | number | The top coordinate (pixels) for menu positioning. |
left | number | The left coordinate (pixels) for menu positioning. |
right | number (optional) | The right coordinate (pixels), alternative horizontal positioning. |
bottom | number (optional) | The bottom coordinate (pixels), alternative vertical positioning. |
[key: string] | unknown (optional) | Additional props passed to the menu container element. |
Component: NodeContextMenu
export function NodeContextMenu({
id,
top,
left,
right,
bottom,
...props
}: INodeContextMenu)
Description
A React functional component that renders a context menu for a given node. It provides buttons to duplicate or delete the node. The menu is positioned absolutely on the page based on the top, left, right, and bottom props.
Parameters
id(string): The node's unique identifier.top(number): Vertical position for the menu.left(number): Horizontal position for the menu.right(number, optional): Alternative horizontal position.bottom(number, optional): Alternative vertical position....props: Additional props spread onto the container<div>.
Returns
JSX element representing the context menu UI.
Usage Example
<NodeContextMenu
id="node-1"
top={100}
left={200}
/>
Implementation Details
Uses
useReactFlow()hook from@xyflow/reactto get flow manipulation methods:getNode(id): Fetches node by ID.addNodes(): Adds new nodes.setNodes(): Updates nodes array.setEdges(): Updates edges array.
Duplicate functionality: Clones the existing node, offsets its position by +50 pixels in both x and y directions, and assigns a new id by appending
-copy.Delete functionality: Removes the node and any edges that originate from it.
Hook: useHandleNodeContextMenu
export const useHandleNodeContextMenu = (sideWidth: number) => { ... }
Description
A custom React hook managing the state and event handlers related to the node context menu. It tracks the menu's visibility and position, handles right-click events on nodes, and closes the menu on pane clicks.
Parameters
sideWidth(number): An offset used to position the context menu horizontally relative to the click event (likely the width of a sidebar or panel).
Returns
An object containing:
Property | Type | Description |
|---|---|---|
|
| Event handler for right-click on nodes, positions and opens the menu. |
|
| Current menu state (position and node id). |
|
| Handler to close the menu when clicking outside. |
|
| Ref to the container DOM node for bounding calculations. |
Usage Example
const { onNodeContextMenu, menu, onPaneClick, ref } = useHandleNodeContextMenu(240);
return (
<div ref={ref} onClick={onPaneClick}>
<ReactFlow onNodeContextMenu={onNodeContextMenu}>
{menu.id && <NodeContextMenu {...menu} />}
</ReactFlow>
</div>
);
Implementation Details
Uses a
useStatehook to keep track of the menu's position and target node.Uses a
useRefhook to reference the container's DOM element for bounding box calculations.On right-click (
onNodeContextMenu), prevents the browser default menu and calculates where to render the context menu based on the mouse event and pane size.The positioning logic considers offsets, and avoids placing the menu off-screen.
The
onPaneClickhandler closes the menu when clicking outside.
Note: Some commented-out code suggests previous attempts to refine menu positioning based on pane boundaries, currently simplified.
Important Implementation Details
Positioning Logic: The menu is positioned absolutely with
topandleftstyles derived from the mouse event coordinates, adjusted by an offset (sideWidth) and a constant (144pixels vertically). This helps avoid overlapping with UI elements like sidebars.Node Duplication: Creates a shallow clone of the existing node, preserving its data and resetting interaction states (
selected: false,dragging: false), and positions it slightly offset to avoid overlap.Node Deletion: Filters out the node and all edges that have the node as a source, cleaning up the graph.
The menu styling is imported from a CSS module
index.lessto scope styles locally.The hook and component are designed to integrate seamlessly with the
@xyflow/reactflow framework.
Interaction with Other Parts of the System
Relies heavily on the
@xyflow/reactpackage, which appears to provide React Flow utilities such as node and edge management.The context menu component expects to be rendered inside a React Flow context, where nodes and edges are managed globally.
The hook
useHandleNodeContextMenuprovides event handlers and state to be attached to the React Flow pane or node components.The CSS module
index.lessprovides styling for the context menu's appearance.Likely used within a larger flow editor or graph visualization application where nodes represent entities or steps in a workflow.
Visual Diagram
componentDiagram
component "NodeContextMenu" {
+duplicateNode()
+deleteNode()
props: INodeContextMenu (id, top, left, right?, bottom?, ...)
}
component "useHandleNodeContextMenu" {
+onNodeContextMenu(event, node)
+onPaneClick()
state: menu (INodeContextMenu)
ref: DOM element ref
}
component "ReactFlow" {
+getNode(id)
+addNodes(node)
+setNodes(fn)
+setEdges(fn)
}
ReactFlow <.. NodeContextMenu : uses
useHandleNodeContextMenu ..> NodeContextMenu : provides menu state & handlers
useHandleNodeContextMenu ..> ReactFlow : event handlers attached to nodes
Summary
This file provides a reusable React UI component and hook to manage a node context menu in a flow-based diagram editor. It allows interactive duplication and deletion of nodes with thoughtful UI positioning and integration with the React Flow management API. The solution balances usability and functionality with clean React hooks and well-defined interfaces.
Additional Notes
The
useHandleNodeContextMenuhook is marked as deprecated, indicating that there might be a newer approach or replacement elsewhere in the project.The commented-out code in the hook hints at ongoing improvements or experimentation with positioning logic, which might be revisited in future iterations.
The file does not export default; both exports are named, allowing selective import.