Events
Every event the editor emits, what it carries, and which one to use for what.
Everything that happens in the editor is an event. Subscribe with on, and keep the function it returns to unsubscribe:
ts
const off = editor.on('select', ({ ids }) => {
console.log(`${ids.length} selected`)
})
off()
In React, useEditorEvent subscribes for the lifetime of a component:
tsx
import { useEditorEvent } from 'canvasflow/react'
function Logger() {
useEditorEvent('action', ({ id, source }) => console.log(`${id} from ${source}`))
return null
}
Document and state#
| Event | Payload | When |
|---|---|---|
change |
{ diff, source } |
Any document change. source is user, remote or system |
state |
{ prev, next, keys } |
Instance state changed (camera, tool, selection, theme…) |
select |
{ ids } |
The selection changed |
tool |
{ id, path } |
The active tool or its state changed |
camera |
{ x, y, z } |
The camera moved |
page |
{ id } |
The current page changed |
history |
{ canUndo, canRedo } |
Undo or redo became available or not |
Shapes#
These carry { shape, point, info }: the shape record, the page point, and the raw input event.
| Event | When |
|---|---|
shape:pointerdown, shape:pointerup |
A pointer pressed or released over a shape |
shape:click, shape:dblclick |
A click or double-click on a shape |
shape:pointerenter, shape:pointerleave |
The pointer moved onto or off a shape |
shape:contextmenu |
A right-click or long-press on a shape |
ts
editor.on('shape:click', ({ shape }) => {
if (shape.meta.href) window.open(String(shape.meta.href))
})
Editing and interface#
| Event | Payload | When |
|---|---|---|
edit-start |
{ id } |
Text editing started on a shape |
edit-end |
{ id, deleted } |
Editing ended. deleted is true when an empty text was removed |
contextmenu |
{ point, shapeId } |
A context menu should open (right-click or long-press) |
action |
{ id, source } |
An action ran |
toast |
{ message, kind, undoable } |
The editor wants to tell the person something |
plugins |
{ installed?, uninstalled? } |
A plugin was installed or removed |
Clipboard and requests#
The editor never opens file pickers or reads the clipboard by itself: it asks the host, and the host (or your app) decides how.
| Event | Payload | When |
|---|---|---|
copy |
{ content, cut } |
Shapes were copied or cut |
request-paste |
{ point } |
Paste was requested at a point |
request-image |
{ point } |
The image tool wants a file |
request-embed |
{ point } |
The embed tool wants a URL |
Low level#
| Event | Payload | When |
|---|---|---|
event |
the normalized input event | Every pointer, wheel, pinch and key event, before tools see it |
dispose |
none | The editor is being disposed |
editor.subscribe(fn) runs fn after anything changes, batched once per change. Use it to re-render your own interface when you don't care about the details.
Which one should I use?#
| To… | Use |
|---|---|
| Save the document | change, ignoring source: 'remote' if a collaborator already saved it |
| Update a "selected" panel | select, or useValue((e) => e.getSelectedIds()) in React |
| Highlight the active tool in your toolbar | tool |
| Track analytics | action |
| Show your own toasts | toast |
| React to clicks on shapes (links, details panels) | shape:click |