Quick start
Build a two-node graph step by step: describe the entities, give them sockets, hold them in state, and drag a wire between them.
You'll build a graph with two nodes and connect them by dragging a wire from one to the other. Your component holds the nodes and wires in React state, and the canvas reports each change you make back to that state. This page assumes you've finished Installation.
Describe two entities
Everything on the canvas is an entity: a plain object with an id, a type, a position
and some data. Nodes are entities, and so are frames, comments, pictures and text.
import type { Entity } from "@kushagradhawan/kookie-flow";const initialEntities: Entity[] = [ { id: "constant", type: "constant", position: { x: 0, y: 0 }, data: { label: "Constant" } }, { id: "viewer", type: "viewer", position: { x: 320, y: 0 }, data: { label: "Viewer" } },];idnames the entity. Wires and change reports refer to it, so it must be unique.typeis any string. Eight names, such asframe,textandimage, are built-in kinds of entity with behaviour of their own. Any other string, likeconstanthere, is a node.positionis the node's top-left corner in world units.ygrows downward, as it does on a web page.data.labelis the title the node shows.
The node is 240 units wide unless you set width, and it's as tall as its contents need. The
entity model chapter describes every field.
Give them sockets
A socket is a point on a node that a wire attaches to. Outputs sit on the node's right edge and inputs sit on its left. Give the first node an output and the second an input:
const initialEntities: Entity[] = [ { id: "constant", type: "constant", position: { x: 0, y: 0 }, data: { label: "Constant" }, outputs: [{ id: "value", name: "Value", type: "float" }], }, { id: "viewer", type: "viewer", position: { x: 320, y: 0 }, data: { label: "Viewer" }, inputs: [{ id: "value", name: "Value", type: "float" }], },];Each socket has an id, a name that the node prints beside it, and a type. float is one
of the socket types the library defines for you. It colours the socket blue, and an input of
that type draws a slider while nothing is wired into it.
A socket's id only has to be unique among that node's inputs, or among its outputs. That's
why both sockets can be called value. Sockets and widgets lists the
built-in types and shows how to add your own.
Hold the graph in state
useGraph keeps the entities and edges in React state and gives you the handlers that update
them. Pass all five values to KookieFlow:
const { entities, edges, onEntitiesChange, onEdgesChange, onConnect } = useGraph({ initialEntities,});return ( <KookieFlow entities={entities} edges={edges} onEntitiesChange={onEntitiesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />);Each handler has its own job:
onEntitiesChangereceives moves, resizes, new entities and deletions.onEdgesChangereceives wires being deleted.onConnectruns when you drop a wire on a socket that accepts it.
The canvas doesn't create an edge when you connect two sockets. It calls onConnect with
the two ends, and useGraph adds the edge to edges. Leave onConnect out and the wire
follows your pointer, then disappears when you let go.
useGraph reads initialEntities once, when the component mounts, and ignores the value on
every later render. Define the array outside the component, so it's created once.
Frame the view
The canvas opens at zoom 1 with the world's origin in the top-left corner of the box, so the
nodes sit against the top-left edge. Call fitView once after mount to centre them. It's a
method on the instance you get by passing a ref to KookieFlow:
const flowRef = useRef<KookieFlowInstance>(null);useEffect(() => { flowRef.current?.fitView({ padding: 80 });}, []);Then add ref={flowRef} to the KookieFlow element. padding leaves space between the nodes
and the edge of the box. fitView zooms out as far as it needs to, and it doesn't zoom in
past 100% unless you pass a larger maxZoom.
Canvas and camera covers the other view methods.
Here is the whole file, running:
Arrow keys move between nodes. Press Enter to reach the focused node's controls, and Escape to come back here.
'use client';import { useEffect, useRef } from 'react';import { KookieFlow, useGraph, type Entity, type KookieFlowInstance,} from '@kushagradhawan/kookie-flow';// Two nodes: one with a float output, one with a float input.const initialEntities: Entity[] = [ { id: 'constant', type: 'constant', position: { x: 0, y: 0 }, data: { label: 'Constant' }, outputs: [{ id: 'value', name: 'Value', type: 'float' }], }, { id: 'viewer', type: 'viewer', position: { x: 320, y: 0 }, data: { label: 'Viewer' }, inputs: [{ id: 'value', name: 'Value', type: 'float' }], },];export default function QuickStartExample() { const { entities, edges, onEntitiesChange, onEdgesChange, onConnect } = useGraph({ initialEntities, }); // Frame both nodes once, whatever width the box turns out to be. const flowRef = useRef<KookieFlowInstance>(null); useEffect(() => { flowRef.current?.fitView({ padding: 80 }); }, []); return ( <div style={{ width: '100%', height: 360 }}> <KookieFlow ref={flowRef} entities={entities} edges={edges} onEntitiesChange={onEntitiesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} /> </div> );}Try the canvas
Click the canvas first. It only answers keys while it has focus, so a page that embeds it keeps its own shortcuts.
- Connect the sockets. Press on either
Valuesocket and drag to the other one. When you let go, the wire stays and the slider on the Viewer's input goes away. - Move a node. Drag it by its body.
- Select several. Drag across empty canvas to draw a selection box. Hold Cmd or Ctrl to add to the current selection, or to click a node out of it.
- Delete. Click a node or a wire, then press Delete or Backspace. Deleting a node also deletes its wires.
- Pan. Hold Space and drag, or drag with the middle mouse button.
- Zoom. Pinch on a trackpad, or hold Cmd or Ctrl and scroll. In your own app a plain scroll zooms too, but on this page it scrolls the page.
- Clear the selection. Press Escape.
Where to go next
Each step on this page has a chapter of its own:
- Controlled and uncontrolled state explains what the canvas reports, and how
to keep the graph in your own store instead of
useGraph. - The entity model describes every field an entity can carry.
- Sockets and widgets covers socket types and the controls on inputs.
- Connections shows how to decide which sockets may connect.
- Canvas and camera covers zoom limits, the grid and the view methods.
- Keyboard lists every key the canvas answers.