Events API
The EventBus provides a publish/subscribe system for reacting to editor events. Use it for auto-save, analytics, custom integrations, or coordinating external UI with the editor state.
Usage
Basic Usagetypescript
const eventBus = engine.getEventBus();
// Subscribe to an event
const unsubscribe = eventBus.on('object:selected', (data) => {
console.log('Selected object IDs:', data.objectIds);
});
// Emit a custom event
eventBus.emit('custom:event', { data: 'value' });
// Unsubscribe when done
unsubscribe();đĄ
Return value
Every
eventBus.on() call returns an unsubscribe function. Always call it when your listener is no longer needed to prevent memory leaks.Multiple Listeners
Multiple Eventstypescript
const eventBus = engine.getEventBus();
// Track multiple events
const unsub1 = eventBus.on('object:added', (data) => {
console.log('Object added:', data.id, data.type);
});
const unsub2 = eventBus.on('object:removed', (data) => {
console.log('Object removed:', data.id);
});
const unsub3 = eventBus.on('object:modified', (data) => {
console.log('Object modified:', data.id, data.properties);
});
// Clean up all listeners
function cleanup() {
unsub1();
unsub2();
unsub3();
}React Integration
In React, subscribe inside a useEffect and return the unsubscribe function as the cleanup:
React Patterntsx
import { useEffect } from 'react';
import { useEditorContext } from '@design-on-web/ui';
function SelectionTracker() {
const engine = useEditorContext();
useEffect(() => {
const eventBus = engine.getEventBus();
const unsubSelected = eventBus.on('object:selected', (data) => {
console.log('Selected:', data.objectIds);
});
const unsubDeselected = eventBus.on('object:deselected', () => {
console.log('Nothing selected');
});
return () => {
unsubSelected();
unsubDeselected();
};
}, [engine]);
return null; // Headless tracker component
}Auto-Save Pattern
Auto-Savetypescript
const eventBus = engine.getEventBus();
// Auto-save pattern
let saveTimeout;
eventBus.on('object:modified', () => {
// Debounce saves to avoid saving on every small change
clearTimeout(saveTimeout);
saveTimeout = setTimeout(() => {
const json = engine.toJSON();
fetch('/api/designs/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: json }),
});
}, 2000);
});
// Track export completion
eventBus.on('export:complete', (data) => {
console.log(`Exported as ${data.format}, size: ${data.blob.size} bytes`);
});Event Reference
Editor Lifecycle
| Name | Type | Default | Description |
|---|---|---|---|
editor:ready | {} | â | Fired when the editor engine is fully initialized and ready for interaction. |
Object Events
| Name | Type | Default | Description |
|---|---|---|---|
object:selected | { objectIds: string[] } | â | Fired when one or more objects are selected on the canvas. |
object:deselected | {} | â | Fired when all objects are deselected. |
object:added | { id: string; type: string } | â | Fired when a new object is added to the canvas. |
object:removed | { id: string } | â | Fired when an object is removed from the canvas. |
object:modified | { id: string; properties: Record<string, unknown> } | â | Fired when an object's properties change (move, resize, rotate, color, etc.). |
Export Events
| Name | Type | Default | Description |
|---|---|---|---|
export:start | { format: string } | â | Fired when an export operation begins. |
export:complete | { format: string; blob: Blob } | â | Fired when an export operation completes successfully. |
export:error | { format: string; error: Error } | â | Fired when an export operation fails. |
Save Events
| Name | Type | Default | Description |
|---|---|---|---|
save:start | {} | â | Fired when a save operation begins. |
save:complete | {} | â | Fired when a save operation completes. |
Plugin Events
| Name | Type | Default | Description |
|---|---|---|---|
plugin:loaded | { name: string } | â | Fired when a plugin is successfully registered. |
plugin:error | { name: string; error: Error } | â | Fired when a plugin fails to load. |
Page Events
| Name | Type | Default | Description |
|---|---|---|---|
page:switched | { index: number } | â | Fired when the active page changes. |
page:added | { index: number } | â | Fired when a new page is added. |
page:removed | { index: number } | â | Fired when a page is removed. |
Version Events
| Name | Type | Default | Description |
|---|---|---|---|
version:created | { id: string; label: string } | â | Fired when a new version snapshot is saved. |
version:restored | { id: string } | â | Fired when a previous version is restored. |
Custom Events
You can emit and listen for your own custom events using the same EventBus. Use a namespace prefix (e.g., myapp:) to avoid collisions with built-in events.
âšī¸
Type safety
The EventBus accepts any string as an event name. For TypeScript projects, consider creating a typed wrapper around the EventBus to get autocomplete and type checking for your custom events.
Next Steps
- Store API â state-based alternative to events
- Commands API â undo/redo command system
- EditorEngine API â methods that trigger events