Learn / Events & interaction

Events & interaction

One event map on the instance; each framework dresses it in its own idiom — DOM events, React callbacks, Vue emits, Angular outputs. Learn the map once and the bindings become predictable.

The instance event map

instance.on('nodes:change',     ({ nodes }) => save(nodes));      // add/remove — live NodeModel[]
instance.on('edges:change',     ({ edges }) => {});
instance.on('selection:change', ({ nodes, edges }) => inspect(nodes));
instance.on('connect',          ({ link }) => {});                 // a wire was completed
instance.on('reconnect',        ({ link, endpoint }) => {});       // 'source' | 'target' moved
instance.on('node:click',       ({ node, world }) => {});          // world = diagram coords
instance.on('node:doubleclick', ({ node, world }) => {});
instance.on('edge:click',       ({ edge, world }) => {});
instance.on('viewport:change',  ({ viewport, zoom }) => {});
// every on() returns an unsubscribe function

The same map, per framework

SurfaceIdiomExample
Plain JSapi.on(...), or bubbling DOM events on <grafloria-flow> el.addEventListener('grafloria-connect', e => e.detail.link)
Reactcallback propsonConnect, onNodeClick, onSelectionChange, onNodesChange
Vueemits (kebab-case)@connect, @node-click, @selection-change, v-model:nodes
Angularmodel writes + outputs[(nodes)], (viewportChanged), (layoutDone); clicks via the engine bus

The element's DOM events (grafloria-ready, -nodes-change, -edges-change, -selection-change, -connect, -node-click, -edge-click, -viewport-change) all bubble and cross shadow boundaries — delegate at document level if you like.

The connection lifecycle, live

While a user drags a wire, the engine's bus narrates it — this is what powers guidance UIs (tint the good targets, explain the refusals):

const bus = instance.getEngine().eventBus;
for (const name of ['connection:start', 'connection:update', 'connection:port-enter',
                    'connection:port-leave', 'connection:complete', 'connection:cancel']) {
  bus.on(name, (payload) => log(name, payload));
}

Live: connection events narrated on screen →

Interaction config — what the user may do

// at creation (a prop in React/Vue: interaction={{ ... }})
render(spec, host, { interaction: { portVisibility: 'always' } });

// at runtime
instance.getEngine().setInteractionConfig({ portVisibility: 'always' });

Framework-level switches cover the common cases directly: readonly (view-only canvas), enablePan / enableZoom / minZoom / maxZoom / zoomSensitivity, fitView, and in Angular also enableSnapping, enableProximityConnect, enableKeyboardNavigation, enableInPlaceEditing and canvasBounds.

Built-in keyboard support ships enabled: ⌘Z/⌘⇧Z history, Delete for selection, arrow-key nudging, and focus-visible navigation with live-region narration for screen readers. You wire nothing.

Where next