Appearance
FlowCanvas — usage examples
FlowCanvas ships as six pre-compiled, per-framework packages from a single .rozie source — install only the one for your framework (no Rozie toolchain, no build-time compile step). Each carries its engine + framework peers as peer dependencies, so you control their versions. The snippets below are the same idiomatic consumption code shown in each package's README; switch the tab to your framework.
Usage
tsx
import { useState } from 'react';
import { FlowCanvas } from '@rozie-ui/rete-react';
export function Demo() {
const [zoom, setZoom] = useState(1);
const nodes = [
{ id: 'a', label: 'Source', x: 0, y: 0, outputs: [{ key: 'out' }] },
{ id: 'b', label: 'Sink', x: 280, y: 60, inputs: [{ key: 'in' }] },
];
const connections = [{ source: 'a', sourceOutput: 'out', target: 'b', targetInput: 'in' }];
return (
<div style={{ height: 400 }}>
<FlowCanvas
nodes={nodes}
connections={connections}
zoom={zoom}
onZoomChange={setZoom}
onConnectionCreated={(c) => console.log('connected', c)}
onNodeMoved={(e) => console.log('moved', e)}
/>
</div>
);
}vue
<script setup lang="ts">
import { ref } from 'vue';
import FlowCanvas from '@rozie-ui/rete-vue';
const zoom = ref(1);
const nodes = [
{ id: 'a', label: 'Source', x: 0, y: 0, outputs: [{ key: 'out' }] },
{ id: 'b', label: 'Sink', x: 280, y: 60, inputs: [{ key: 'in' }] },
];
const connections = [{ source: 'a', sourceOutput: 'out', target: 'b', targetInput: 'in' }];
</script>
<template>
<div style="height: 400px">
<FlowCanvas
:nodes="nodes"
:connections="connections"
v-model:zoom="zoom"
@connection-created="(c) => console.log('connected', c)"
@node-moved="(e) => console.log('moved', e)"
/>
</div>
</template>svelte
<script lang="ts">
import FlowCanvas from '@rozie-ui/rete-svelte';
let zoom = $state(1);
const nodes = [
{ id: 'a', label: 'Source', x: 0, y: 0, outputs: [{ key: 'out' }] },
{ id: 'b', label: 'Sink', x: 280, y: 60, inputs: [{ key: 'in' }] },
];
const connections = [{ source: 'a', sourceOutput: 'out', target: 'b', targetInput: 'in' }];
</script>
<div style="height: 400px">
<FlowCanvas
{nodes}
{connections}
bind:zoom
onconnectioncreated={(c) => console.log('connected', c)}
onnodemoved={(e) => console.log('moved', e)}
/>
</div>ts
import { Component } from '@angular/core';
import { FlowCanvas } from '@rozie-ui/rete-angular';
@Component({
selector: 'app-demo',
standalone: true,
imports: [FlowCanvas],
template: `
<div style="height: 400px">
<FlowCanvas
[nodes]="nodes"
[connections]="connections"
[(zoom)]="zoom"
(connection-created)="onConnect($event)"
(node-moved)="onMoved($event)"
/>
</div>
`,
})
export class DemoComponent {
zoom = 1;
nodes = [
{ id: 'a', label: 'Source', x: 0, y: 0, outputs: [{ key: 'out' }] },
{ id: 'b', label: 'Sink', x: 280, y: 60, inputs: [{ key: 'in' }] },
];
connections = [{ source: 'a', sourceOutput: 'out', target: 'b', targetInput: 'in' }];
onConnect(c: any) { console.log('connected', c); }
onMoved(e: any) { console.log('moved', e); }
}tsx
import { createSignal } from 'solid-js';
import { FlowCanvas } from '@rozie-ui/rete-solid';
export function Demo() {
const [zoom, setZoom] = createSignal(1);
const nodes = [
{ id: 'a', label: 'Source', x: 0, y: 0, outputs: [{ key: 'out' }] },
{ id: 'b', label: 'Sink', x: 280, y: 60, inputs: [{ key: 'in' }] },
];
const connections = [{ source: 'a', sourceOutput: 'out', target: 'b', targetInput: 'in' }];
return (
<div style={{ height: '400px' }}>
<FlowCanvas
nodes={nodes}
connections={connections}
zoom={zoom()}
onZoomChange={setZoom}
onConnectionCreated={(c) => console.log('connected', c)}
onNodeMoved={(e) => console.log('moved', e)}
/>
</div>
);
}ts
import '@rozie-ui/rete-lit';
// <rozie-flow-canvas> is a custom element. Set `nodes`/`connections` as
// properties, bind `zoom`, and listen for graph events.
const el = document.querySelector('rozie-flow-canvas');
el.nodes = [
{ id: 'a', label: 'Source', x: 0, y: 0, outputs: [{ key: 'out' }] },
{ id: 'b', label: 'Sink', x: 280, y: 60, inputs: [{ key: 'in' }] },
];
el.connections = [{ source: 'a', sourceOutput: 'out', target: 'b', targetInput: 'in' }];
el.zoom = 1;
el.addEventListener('zoom-change', (e) => { el.zoom = e.detail; });
el.addEventListener('connection-created', (e) => console.log('connected', e.detail));Imperative handle
Beyond props and events, FlowCanvas exposes imperative methods (declared once in the .rozie source via $expose). Grab a handle through your framework's native ref mechanism and call them directly:
tsx
import { useRef } from 'react';
import { FlowCanvas, type FlowCanvasHandle } from '@rozie-ui/rete-react';
const flow = useRef<FlowCanvasHandle>(null);
// <FlowCanvas ref={flow} ... />
flow.current?.addNode({ id: 'c', label: 'New', x: 100, y: 200, inputs: [{ key: 'in' }] });
flow.current?.zoomToFit();
const editor = flow.current?.getEditor();vue
<script setup>
import { ref } from 'vue';
const flow = ref(); // template ref
</script>
<template>
<FlowCanvas ref="flow" />
<button @click="flow.zoomToFit()">Fit</button>
</template>svelte
<script>
let flow; // component instance via bind:this
</script>
<FlowCanvas bind:this={flow} />
<button onclick={() => flow.zoomToFit()}>Fit</button>ts
@Component({ /* ... */ })
export class DemoComponent {
@ViewChild(FlowCanvas) flow!: FlowCanvas; // or the viewChild() signal
fit() { this.flow.zoomToFit(); }
editor() { return this.flow.getEditor(); }
}tsx
import { FlowCanvas, type FlowCanvasHandle } from '@rozie-ui/rete-solid';
let handle: FlowCanvasHandle | undefined;
// The ref callback receives the HANDLE object (not the DOM node).
<FlowCanvas ref={(h) => (handle = h)} />;
handle?.zoomToFit();
const editor = handle?.getEditor();ts
// The custom element IS the handle — its exposed methods are public
// element methods.
const el = document.querySelector('rozie-flow-canvas');
el.zoomToFit();
const editor = el.getEditor();See also
- FlowCanvas — showcase & API — the full prop / event / slot / handle reference, theming, and accessibility.
- FlowCanvas comparison — how it stacks up against the per-framework libraries.
- FlowCanvas — live demo — the real package running in the page, plus the one
.roziesource and all six generated outputs.