Diagram - Clipboard
Copy diagram fragments, paste with new identities and keep native input, transport and host approval ownership explicit.
#Usage
import { Diagram } from '@primeui/vue-diagram';<Diagram.Root :store="store" page-id="page">
<Diagram.CommandButton command-id="copy" v-slot="{ getButtonProps }">
<button v-bind="getButtonProps({ type: 'button' })">Copy</button>
</Diagram.CommandButton>
<Diagram.CommandButton command-id="paste" v-slot="{ getButtonProps }">
<button v-bind="getButtonProps({ type: 'button' })">Paste</button>
</Diagram.CommandButton>
<Diagram.Viewport label="Workflow editor" style="height: 24rem" />
</Diagram.Root>Native clipboard events and toolbar transport use the same session controller. Destination page, layer and parent ownership must be valid.
This skeleton assumes an initialized store with page page. Use First Diagram for model creation, style imports and store disposal.
Use Copy/Paste to transfer a diagram subgraph and Duplicate to make a local copy. Both allocate new Diagram IDs and retain safe business payloads. Clipboard transport is application/browser-owned; semantic paste belongs to the session.
#Use native events or the toolbar transport
Select both cards. Focus the canvas for native Ctrl/Cmd+C, X or V, or use Copy, Cut and Paste buttons. Use Transport failure scenario and try denied cut to see an error without deleting content. Use the native text field to compare clipboard/IME ownership.
Native browser clipboard events use the focused viewport. Native inputs, textareas, contenteditable regions, selected text and composing input retain clipboard ownership. C/X/V keys do not also dispatch duplicate editor commands; the native clipboard event is the single path.
The viewport configures toolbar/context-menu clipboard actions through
navigator.clipboard when available. session.clipboard.run('copy' | 'cut' | 'paste', transport?, target?) returns a Promise of clipboard state. An explicit
application transport implements async write(text, context) and read(context);
context has request ID, revision and the portable advisory cancellation signal.
Without an argument, run uses the configured transport.
Unsupported transport and permission denial are visible diagnoses. There is no silent internal clipboard fallback. Duplicate is a separate local semantic operation; it does not claim to have written the system clipboard.
Cut deletes only after a successful write, with stale ownership rechecked.
Toolbar cut waits for the write Promise; native event setData success counts
as acceptance because browsers expose no later operating-system acknowledgement
for that event. A failed or stale write cannot delete the selected graph.
A committed cut deletes owned/incident content in one Undo unit.
A write may have reached external storage before cancellation. cancel() stops
local work but cannot undo that write. A stale read cannot paste over newer work.
Surface state.diagnostics near the action instead of claiming that a failed
transport populated the clipboard.
#Paste on the same page or into another container/page
Capture both cards, then paste on the source page or into the destination container. The example shows two stable page sessions sharing one store; the destination session performs its paste so its page geometry and policy apply. Repeat paste to allocate fresh IDs each time.
This example deliberately exposes an application buffer using capture() and
pasteText(). It is an explicit semantic example, not a recovery path after
system clipboard denial. This abbreviated call assumes a valid captured fragment
and the session mounted on the destination page:
session.clipboard.pasteText(captured.text, {
pageId: 'destination',
layerId: 'destination-layer',
parentId: 'copy-container',
offset: { x: 40, y: 40 }
});DiagramPasteTarget | Contract |
|---|---|
pageId, layerId | Required existing IDs; page matches the receiving session, layer belongs to that page and is editable. |
parentId | Optional destination container on that page/layer; must be eligible for containment. Omitted means page-root ownership. |
offset | Optional translation in destination page-world units; default { x: 24, y: 24 }. |
Captured root geometry is source page-world geometry. Paste applies the offset, then converts roots into the destination parent frame. Internal child coordinates stay local. Waypoints, Bézier controls and label frames follow the transformation; runtime measurement/routing caches are not copied. Duplicate preserves each source root's parent and layer while applying its optional offset.
New IDs are allocated for nodes, connectors, ports, labels and phases. Parent,
endpoint, lane and phase references are remapped together. Internal page links
point to remapped destination content; external links become inert provenance.
extensions.primeuiData active binding identity becomes primeuiClipboard
provenance: paste does not invoke a binding writer or claim an existing business
identity. Other safe application payload/extension content survives. Bind a local
copy explicitly if your application needs a new business record.
#Handle dangling endpoints and graph closure
Copy includes selected nodes and descendants, connectors owned by descendants, and connections whose two endpoints are copied. Explicitly selected connectors are also included. An endpoint outside that graph becomes a captured free point.
In the destination example, capture Review plus its connector, leaving Approve
outside the fragment. Paste rejects the whole graph by default. Toggle the
explicit connectionOptions.allowDangling policy to allow its free endpoint.
Ordinary copy of Review alone does not automatically bring every incident edge.
No rejected paste leaves partial nodes behind.
A full pool includes lanes, phases and membership. A partial lane copy is rejected; copy the complete pool. Ordinary content copied out of a lane loses its old phase membership. Notation references need their own closure rules and installed notation module, rather than a generic ID replacement. Continue with BPMN reuse, Activity profiles and Sequence fragments for the supported semantic fragments and rejection rules.
#Separate paste approval from host acceptance
Paste/duplicate submit one composite command through the connection editor.
Current direction, capacity, type, cycle, dangling, containment and model rules
validate the prospective graph together. When requireApproval is true, resolve
the immutable complete composite once with
session.connections.resolve(request.id, accepted).
After connection approval, a controlled store still requires host acceptance. Rejecting/cancelling before submission creates nothing. Cancel/dispose after submission leaves the host proposal with the application. A read-only change does not withdraw a submitted proposal; the host must enforce its own policy. A successful paste is one Undo unit. See the two-stage example in Controlled State.
#Read state and diagnose input
| Clipboard member | Contract |
|---|---|
capture(ids?) | Defaults to current selection. Returns { ok: true, fragment, text, diagnostics } or { ok: false, diagnostics }; no transport write or model edit. |
pasteText(text, target?) | Synchronous semantic submission returning an edit result, which may await approval/host acceptance. Default target is this session's page and first visible unlocked layer. |
duplicate(ids, offset?) | Local remapping/approval; no clipboard transport. |
configure(transport?) | Sets application transport; undefined clears it. Diagram viewport owns its browser adapter. |
availability(kind, ids?, requireTransport?) | Current capability/diagnostics; IDs default to selection, transport requirement defaults true. Execution checks again. |
getSnapshot(), subscribe(listener) | Readonly state and subscription disposer. |
status | idle, reading, writing, copied, cut, pending, committed, rejected, cancelled, stale, disposed. |
diagnostics, result | Readable diagnostics and optional underlying edit result. |
cancel(), dispose() | Cancel local owned work; roots dispose their session-owned controller. |
Fragments have format: 'primeui.diagram.fragment', version: 1, a self-contained
native model and selectedIds. Public parseDiagramClipboard(text) validates
without committing. Limits are 8,000,000 text characters, 1,000 nodes and 4,000
connectors, plus the native depth/value/geometry limits. Unknown versions,
malformed/oversized payloads and invalid destinations create no transaction.
Clipboard fragments do not execute renderer code, HTML, scripts, migration
callbacks or network requests.
Use controller diagnostics for transport errors and the connection/store result for pending decisions. Unsubscribe your listeners at teardown; the Diagram root cleans up its session. If you create a session yourself, follow SSR and Lifecycle.
Restart example restores the local fixture and clears its history. It does not reset an external service.