The Diagram Component
<Diagram /> is the root you reach for once you move from @joint/react into JointJS+. It is a <GraphProvider /> that also owns the diagram-level models the Plus features build on: the selection collection, the command manager behind undo/redo, the copy/paste clipboard, and an optional spatially indexed graph. Each one turns on with a single prop. It also wires up JointJS+'s built-in interactions (pan, zoom, selection, undo/redo, copy/paste), on by default, and each becomes active once its backing model or feature is in place. Wrap your diagram in <Diagram /> and you get those models and interactions without extra setup; the matching hooks read them directly.
<Diagram /> is a JointJS+ component from @joint/react-plus. It is a drop-in upgrade of <GraphProvider />, so everything you know about graph state still applies.
Diagram vs GraphProvider
Every <GraphProvider> prop (initialCells, cellNamespace, cellModel) works on <Diagram> unchanged, so the swap is a one-word change. The difference is the models: if your tree only reads and writes graph state (cells, positions, data), <GraphProvider> is the right root; reach for <Diagram> when you add a feature that needs a Plus model or want the built-in interactions, and enable it with its prop.
// State only: GraphProvider is enough
<GraphProvider initialCells={cells}>…</GraphProvider>
// Selection, undo/redo, clipboard, or built-in interactions: use Diagram
<Diagram initialCells={cells} history>…</Diagram>
What Diagram owns
<Diagram> owns diagram-level models, each tied to a prop. One, the selection collection, is always on; the rest are created only when you pass their prop.
The selection collection is always present. As soon as you use <Diagram>, the component creates and holds an mvc.Collection; <Selection> and the selection hooks bind to it automatically. It powers Selection.
Pass history and you get the command manager. Without it, every graph mutation is permanent the moment it happens; with it, the manager records each mutation and useGraphHistory() exposes undo / redo. The history prop controls Undo & Redo.
The clipboard prop adds the clipboard behind copy / cut / paste, and useClipboard() exposes it and its actions.
The spatialIndex prop backs the graph with a quad-tree, which speeds up area / point / under-element queries on large diagrams.
<Diagram history /> // undo/redo
<Diagram history={{ stackLimit: 50 }} /> // configured
<Diagram clipboard /> // copy/paste
<Diagram spatialIndex /> // quad-tree spatial queries
Pass true to accept the defaults, or an options object to tune the underlying model. Both forms create the model; omitting the prop leaves it off.
Built-in interactions
<Diagram> also wires JointJS+'s standard pointer and keyboard interactions for you, on by default, so you rarely hand-wire the basics. You don't switch each interaction on individually. Instead, each one turns on automatically once its backing model or feature is present:
| Interaction | Trigger | Active once the diagram has |
|---|---|---|
| Pan and zoom | blank-drag, wheel, Ctrl/Cmd + wheel, pinch | a <PaperScroller> |
| Select, toggle, region-select | click, Cmd/Ctrl + click, Shift + drag | a <Selection> |
| Delete the selection | Delete, Backspace | a <Selection> |
| Clear the selection | Escape | a <Selection> |
| Select all | Ctrl/Cmd + A | a <Selection> |
| Undo / redo | Ctrl/Cmd + Z, Shift + Ctrl/Cmd + Z | the history prop |
| Copy / cut / paste | Ctrl/Cmd + C / X / V | the clipboard prop (with a <Selection>) |
So a bare <Diagram> around a plain <Paper> adds nothing on its own; as you mount <PaperScroller> or <Selection>, or set history / clipboard, their interactions come online with no manual wiring.
<Diagram initialCells={cells}>…</Diagram> // on (for whatever features you add)
<Diagram interactions={false}>…</Diagram> // opt out entirely
<Diagram interactions={{ paperScroller: false }}>…</Diagram> // keep the rest, drop pan & zoom
Pass false to turn the whole layer off, or an object to disable specific parts: the boolean flags paperScroller, selection, clipboard, commandManager, and keyboard each default to on; wheelAction defaults to 'pan' (or 'zoom' / false).
keyboard is the master switch for all shortcuts: set it to false and no key bindings are created, whatever the other flags say. commandManager gates only the undo/redo shortcut, so the history model keeps recording even with it off; you just lose the Ctrl/Cmd+Z binding.
The Shift+drag rubber-band has its own option, selectionRegion, so you can tune or disable just the region without touching the rest of selection. Pass false to drop only the rubber-band (click-to-select and Cmd/Ctrl+A stay), an options object to configure it (region type, one of 'rectangular', 'polygon', or 'range', plus selectLinks, live, and more), or a callback to decide the region per gesture. It does nothing when selection is false.
<Diagram interactions={{ selectionRegion: false }}>…</Diagram> // keep click-select, drop the rubber-band
<Diagram interactions={{ selectionRegion: { type: 'range' } }}>…</Diagram> // configure the region
To register shortcuts of your own beyond these defaults, see Custom Keyboard Shortcuts.