Diagram - Slots and contexts

Root, node and part injection, template envelopes and copied UI projection.

#Usage

import { Diagram } from '@primeui/vue-diagram';
<Diagram.Root :store="store" page-id="page">
    <Diagram.NodeDef node-type="task" v-slot="{ node, actions }">
        <strong>{{ node.data?.['title'] }}</strong>
        <button type="button" data-diagram-interactive @click="actions.setData({ title: 'Reviewed' })">Mark reviewed</button>
    </Diagram.NodeDef>
    <Diagram.Viewport label="Review workflow" style="height: 24rem" />
</Diagram.Root>

This skeleton assumes an initialized store with page page. Use First Diagram for model creation, style imports and store disposal.

Diagram supplies readonly scene/model values and explicit actions to custom content. Place each part under the ancestor that provides its context. Vue scoped slots supply plain values, while child components use named accessors for readonly reactive refs.

#Injection scopes

useDiagramContext() reads the nearest root. It exposes readonly refs for text, contentAvailability, store, model, session, interaction, scene, and geometryVersion, plus measurements.invalidate(ids?) and setConnectionType(type).

Read refs with .value in setup. Destructure refs before using them as top-level template bindings. Do not call context accessors in the parent that merely declares the provider. A reactive child example shows model and selection readouts without a root template ref.

ProviderAccessor / placement
RootuseDiagramContext() beneath Diagram.Root.
NodeuseDiagramNodeContext() inside mounted node content.
InspectoruseDiagramInspectorContext() inside Diagram.Inspector.
User handleuseDiagramUserHandleContext() inside Diagram.UserHandle.
Context menuuseDiagramContextMenuContext() inside Diagram.ContextMenu.
TooltipuseDiagramTooltipContext() inside Diagram.Tooltip.

API lists all six public typed keys. Workspace, persistence, palette and notation services use their named accessors under matching hosts.

#Node definitions

Diagram.NodeDef registers node body content under a root. node-type selects an exact type; omitting it supplies a fallback. The last matching declaration wins. Port definitions follow the same rule independently.

This excerpt belongs inside a root with task nodes:

<Diagram.NodeDef node-type="task" v-slot="{ node, actions }">
    <button type="button" data-diagram-interactive @click="actions.setData({ title: 'Reviewed' })">{{ node.data?.title }}</button>
</Diagram.NodeDef>

The slot has plain readonly values, not refs or an implicit context envelope. node is the authored record, geometry is the effective scene node, and actions changes content or geometry through the current node owner. The actions include setData, content, rotate, edit, and availability.

A component rendered inside the definition can use useDiagramNodeContext(). Its node and geometry are computed refs; its actions object has the same public operations.

#Ports definitions

Diagram.Field needs node context and a field name. It owns draft/save reconciliation for a native input or textarea. Bind the returned props to the actual control:

<Diagram.NodeDef node-type="task">
    <Diagram.Field name="title" v-slot="{ getInputProps }">
        <input aria-label="Task title" v-bind="getInputProps()" />
    </Diagram.Field>
</Diagram.NodeDef>

Diagram.NodePortsDef supplies readonly ports beside the clipped node body. Diagram.Port attaches to an existing saved port ID and returns getPortProps. It measures the native anchor and, in port-definition content, supplies connection interaction. It does not create a saved port.

A matching Diagram.NodePortsDef replaces native decorative dots. It uses the same optional type matching and registration lifetime as Diagram.NodeDef, but resolves independently of the body. It renders once per detailed node beside the clipped body, within the same transformed host and node context. Batched overview nodes do not mount the slot.

The ports slot extends the body slot's node, geometry and actions with readonly ports. Each has an id and node-local position from configured layout before DOM anchor overrides. Position controls from that configured point: the origin is (0, 0) before geometry.transform, with no extra localBounds offset.

Inside this region Diagram.Port measures the anchor and owns connection interaction, replacing that endpoint's built-in control. Outside it the part only measures an anchor in node content. The region bypasses body-shape clipping; viewport and ancestor-container clipping still apply. Port content expands neither intrinsic body size nor Fit bounds. See Ports for styling, acquisition, disabled controls and keyboard behavior.

getInputProps, getPortProps, getButtonProps, getTriggerProps, and getFocusProps accept optional application props. They merge refs and run application handlers before Diagram handlers. A prevented event skips Diagram handling. Pass application handlers into the getter so this ordering is preserved; retain required ARIA attributes.

#Overlay template envelopes

<Diagram.CommandButton command-id="undo" v-slot="{ getButtonProps }">
    <button type="button" v-bind="getButtonProps()">Undo</button>
</Diagram.CommandButton>

The command part supplies native disabled state, aria-disabled, the current reason, and execution. It renders no extra button. The caller supplies its accessible label.

Slot ownerPayloadContext accessor
Diagram.InspectorselectedIds, nodes, commands, execute, availability, applyuseDiagramInspectorContext()
Diagram.UserHandlecommand, node, position, executeuseDiagramUserHandleContext()
Diagram.ContextMenucommands, execute, closeuseDiagramContextMenuContext()
Diagram.TooltiptextuseDiagramTooltipContext()
Root diagnosticsdiagnosticsRoot geometry diagnostics through context.

Custom menu content keeps reachable menu items and the runtime focus/dismissal contract. Tooltip triggers use getTriggerProps; actionable controls need their own visible interface. defaultPresentation controls the default menu/tooltip presentation, not placement or lifetime.

#Diagnostic and palette feedback

Root descendants can read toolbar, selection inspector, and explorer presentation through the public accessors. Workspace and persistence state require their explicit hosts. Palette and notation accessors require their optional providers and imports. API lists keys, entries, and lifetimes.

Presentation snapshots are readonly. Use actions such as setConnectionType or the documented set<Field> action instead of assigning to model refs. Copied components may support named v-model props of their own; those contracts do not make root value two-way.

The root diagnostics slot receives { diagnostics } inside one root-owned alert. Keep replacement content free of another alert. showDefaultDiagnostics changes default diagnostics presentation independently of licensing. Palette feedback is provided by its palette owner; replacement content keeps that owner’s single polite live region.

#Copied UI projection

DiagramEditorUI exposes named toolbar, utilities, status, start, canvas, and end slots. They place application components around the canvas. DiagramCanvasUI provides a default slot for the viewport. These local UI slots do not establish a new store or session. See UI parts.

Collapsing a sidebar preserves its mounted body state. Virtualization can destroy a node view, so saved data belongs in the store. See Node UI, Overlays and SSR and lifecycle.