npm i rete-context-menu-plugin
To improve convenience and code reusability, it is recommended to create separate classes for nodes:
class NodeA extends ClassicPreset.Node {
constructor(socket: ClassicPreset.Socket) {
super("NodeA");
this.addControl("port", new ClassicPreset.InputControl("text", {}));
this.addOutput("port", new ClassicPreset.Output(socket));
}
}
/// class NodeB extends ...
type Node = NodeA | NodeB;
type Schemes = GetSchemes<Node, Connection<Node, Node>>;
For a simple solution, use the classic preset and specify a list of labeled items along with a function that returns the required node
import { ContextMenuExtra, ContextMenuPlugin, Presets as ContextMenuPresets } from "rete-context-menu-plugin";
type AreaExtra = ReactArea2D<Schemes> | ContextMenuExtra;
const contextMenu = new ContextMenuPlugin<Schemes>({
items: ContextMenuPresets.classic.setup([
["NodeA", () => new NodeA(socket)],
["NodeB", () => new NodeB(socket)]
])
});
area.use(contextMenu);
But this is not sufficient as the render plugin is responsible for visualization
Currently, the visualization of the context menu is possible using rendering plugins for React.js, Vue.js, Angular, Svelte and Lit.
import { Presets } from "rete-react-plugin"; // or rete-vue-plugin, rete-angular-plugin, rete-svelte-plugin, @retejs/lit-plugin
render.addPreset(Presets.contextMenu.setup());
For a comprehensive guide on how to connect a specific renderer plugin to your stack version, please follow the guide for React.js, Vue.js, Angular, Svelte or Lit
Clicking on the free space opens up a menu that displays the available nodes for creation, or simply click on an existing node to delete it.
In order to specify node item as subitem, you can use the same definition using an array instead of a factory function:
const contextMenu = new ContextMenuPlugin<Schemes>({
items: ContextMenuPresets.classic.setup([
["Math", [
["Number", () => new NumberNode()],
]]
])
})
While the classic preset lets you briefly specify items for the main menu and node-specific menu, it might not offer enough flexibility. In such cases, you can define your own menu items:
const contextMenu = new ContextMenuPlugin<Schemes>({
items(context, plugin) {
if (context === 'root') {
return {
searchBar: false,
list: [
{ label: 'Custom', key: '1', handler: () => console.log('Custom') },
{
label: 'Collection', key: '1', handler: () => null,
subitems: [
{ label: 'Subitem', key: '1', handler: () => console.log('Subitem') }
]
}
]
}
}
return {
searchBar: false,
list: []
}
}
})
where context
is 'root'
, node instance or connection instance
Check out the complete result on the Context menu example page.