Copy & Paste
The clipboard lets people copy, cut, and paste cells. Turn it on with a single prop to get the keyboard shortcuts automatically, or call its operations from your own buttons and menus.
Enabling the clipboard
Set the clipboard prop on <Diagram> to switch the feature on. Pass true for the defaults, or an options object such as clipboard={{ useLocalStorage: false }} to configure it (see Persisting the clipboard).
import { Diagram, Paper, Selection } from '@joint/react-plus';
export default function App() {
return (
<Diagram initialCells={initialCells} clipboard>
<Paper renderElement={renderElement}>
<Selection />
</Paper>
</Diagram>
);
}
The useClipboard hook works on its own once the clipboard is on. Adding a Selection does two more things: it powers the keyboard shortcuts below, and it gives copy and cut a live set of selected cells to act on. Without a selection you can still copy by handing the clipboard explicit cells.
A complete example
Select a card and copy, cut, or paste it from the toolbar or with the keyboard shortcuts. Right-click the canvas to paste at the pointer. A selected card shows a colored ring, and selecting more than one draws a box around the group. Drag the blank canvas to pan and use the wheel to zoom.
Each piece has its own section below: the hook behind the toolbar, paste-at-cursor behind the right-click menu, the keyboard shortcuts, and how the clipboard persists.
Driving the clipboard yourself
useClipboard returns the clipboard operations, each already bound to the diagram's graph. Copy and cut accept whatever you hand them: a selection collection, an array of cells, or an array of cell ids. Paste adds the clipboard's contents to the graph and returns the cells it created, so you can pass them straight to selectCells to leave the fresh copies selected.
import { useClipboard, useSelection } from '@joint/react-plus';
function ClipboardButtons() {
const { copyCells, pasteCells } = useClipboard();
const { collection, selectCells } = useSelection();
return (
<>
<button onClick={() => copyCells(collection)}>Copy</button>
<button onClick={() => selectCells(pasteCells({ translate: { dx: 24, dy: 24 } }))}>
Paste
</button>
</>
);
}
The translate offset shifts each paste so the copy does not land exactly on top of the original. cutCells mirrors copyCells but removes the originals from the graph. To duplicate the current selection in one step, copy it and paste it back: call copyCells(collection) followed by pasteCells({ translate }).
To disable a paste control while the clipboard is empty, read the clipboard reactively with useCells. The same approach against the selection collection drives the enabled state of copy and cut.
const { clipboard } = useClipboard();
const isClipboardEmpty = useCells(clipboard, (cells) => cells.length === 0);
The hook also returns clearClipboard to empty the clipboard and isClipboardEmpty for a one-off check when you do not need a reactive value. For anything these operations do not cover, useClipboard().clipboard is the live ui.Clipboard instance itself.
Copy and cut are shallow by default. To bring a container's embedded children along, pass deep: true, for example copyCells(collection, { deep: true }). See Containers & grouping.
Pasting at the cursor
pasteCellsAtPoint drops the clipboard at a point you choose instead of a fixed offset. A paper context-menu handler hands you the pointer position in paper coordinates, which is exactly what this operation wants.
const { pasteCellsAtPoint } = useClipboard();
const { selectCells } = useSelection();
function pasteHere(point: { x: number; y: number }) {
selectCells(pasteCellsAtPoint(point));
}
By default the pasted group centers on that point. The origin option re-anchors it, for example to the top-left corner, so the cells land below and to the right of the cursor instead of around it.
Keyboard shortcuts
With the diagram's built-in interactions on (the default), an enabled clipboard, and a Selection present, Ctrl/Cmd+C, Ctrl/Cmd+X, and Ctrl/Cmd+V are wired for you. The shortcuts act on the current selection, which is why the selection feature is part of the requirement. Switch them off with interactions={{ clipboard: false }} when you want to drive copy and paste only from your own controls.
For every interaction flag, see Built-in interactions. To bind your own shortcuts beyond copy, cut, and paste, see Custom Keyboard Shortcuts.
Persisting the clipboard
By default the clipboard saves copied cells to the browser's local storage, so a copy survives a page reload and is shared across browser tabs on the same origin. Set useLocalStorage to false to keep the clipboard in memory only.
<Diagram initialCells={initialCells} clipboard={{ useLocalStorage: false }}>
{/* ... */}
</Diagram>
This setting is locked in when the clipboard is first created, so changing it later has no effect. The clipboard accepts further options, such as link styling and a custom clone routine. See the ui.Clipboard reference for the full list.