Commands API
Design on Web uses a command-based undo/redo system. Every user action that modifies the canvas is recorded as a command on a stack, allowing full undo and redo support.
Undo and Redo
Basic Undo/Redotypescript
// Undo the last operation
engine.undo();
// Redo the last undone operation
engine.redo();
// Check if undo/redo is available
if (engine.canUndo()) {
engine.undo();
}
if (engine.canRedo()) {
engine.redo();
}đĄ
Keyboard shortcuts
The built-in EditorShell UI already handles
Ctrl+Z (undo) and Ctrl+Shift+Z (redo) keyboard shortcuts. You only need the API for custom UI or programmatic control.React Hook
The useHistory hook provides a convenient interface for undo/redo in React components:
useHistory Hooktsx
import { useHistory } from '@design-on-web/ui';
function UndoRedoToolbar() {
const { undo, redo, canUndo, canRedo } = useHistory();
return (
<div className="toolbar">
<button onClick={undo} disabled={!canUndo} title="Undo (Ctrl+Z)">
Undo
</button>
<button onClick={redo} disabled={!canRedo} title="Redo (Ctrl+Shift+Z)">
Redo
</button>
</div>
);
}Store State
You can also read undo/redo availability from the store:
Store Subscriptiontsx
import { useEditorStore } from '@design-on-web/ui';
function UndoIndicator() {
const canUndo = useEditorStore((s) => s.canUndo);
const canRedo = useEditorStore((s) => s.canRedo);
return (
<span>
{canUndo ? 'Changes can be undone' : 'Nothing to undo'}
{' | '}
{canRedo ? 'Changes can be redone' : 'Nothing to redo'}
</span>
);
}Built-in Commands
The following command types are used internally to track operations:
Command Types
| Name | Type | Default | Description |
|---|---|---|---|
AddObjectCommand | Command | â | Records adding a shape, text, or image to the canvas. Undo removes the object; redo re-adds it. |
RemoveObjectCommand | Command | â | Records removing an object from the canvas. Undo re-adds the object; redo removes it again. |
TransformCommand | Command | â | Records any property change on an object: position, size, rotation, fill, stroke, opacity, text content, effects, z-order, etc. Undo restores previous values; redo re-applies the changes. |
âšī¸
Automatic tracking
You do not need to create commands manually. The engine automatically wraps all operations in the appropriate command type and pushes them to the undo stack.
Operations Tracked
Every canvas-modifying operation is automatically recorded. Here is a comprehensive list of operations that support undo/redo:
Tracked Operationstypescript
// All of these operations are automatically added to the undo stack:
// Adding objects
engine.addShape('rect', { left: 100, top: 100, fill: '#4f46e5' });
engine.addText('Hello', { left: 200, top: 200 });
await engine.addImage('https://example.com/img.jpg');
// Removing objects
engine.removeObject(objectId);
// Moving, resizing, rotating objects (via mouse or API)
engine.applyProperties(objectId, { left: 300, top: 300 });
// Changing fill, stroke, opacity, etc.
engine.applyProperties(objectId, { fill: '#ff0000', opacity: 0.5 });
// Applying text effects
engine.applyTextShadow(textId, { color: '#000', blur: 4, offsetX: 2, offsetY: 2 });
engine.applyTextOutline(textId, { color: '#000', width: 2 });
// Applying gradients
engine.applyGradientFill(objectId, {
type: 'linear',
colorStops: [{ offset: 0, color: '#f00' }, { offset: 1, color: '#00f' }],
});
// Z-order changes
engine.bringForward(objectId);
engine.sendToBack(objectId);
// Freehand drawing strokes
engine.setDrawingMode(true);
// ... user draws ... each stroke is one undo stepCommand Stack
The command stack has a configurable maximum depth:
- Default limit: 50 operations
- When the stack exceeds the limit, the oldest commands are discarded
- Performing a new action after undoing clears the redo stack (you cannot redo after making a new change)
- Freehand drawing strokes are batched â each complete stroke counts as one undo step, not individual brush points
â ī¸
Stack limit
The 50-operation limit exists to prevent excessive memory usage. For most design workflows, this is sufficient. The limit is an internal constant and is not currently configurable via the public API.
Next Steps
- EditorEngine API â methods that create commands
- Events API â listen for changes
- Store API â read canUndo/canRedo state