Undo & Redo
FlowDrop provides built-in undo/redo that tracks every workflow change.
Keyboard Shortcuts
Section titled “Keyboard Shortcuts”| Shortcut | Action |
|---|---|
Ctrl/Cmd + Z | Undo |
Ctrl/Cmd + Shift + Z | Redo |
These work automatically — no configuration needed.
How It Works
Section titled “How It Works”FlowDrop’s history store takes snapshots of the entire workflow state. Each change (node add/remove/move, edge add/remove, config change) pushes a new snapshot onto the undo stack.
- Undo restores the previous snapshot and pushes the current state onto the redo stack
- Redo restores the next snapshot from the redo stack
- Making a new change after undoing clears the redo stack
Programmatic Access
Section titled “Programmatic Access”import { getCanUndo, getCanRedo, historyActions } from '@flowdrop/flowdrop/editor';
// Check availabilityconst canUndo = getCanUndo(); // boolean (reactive in Svelte)const canRedo = getCanRedo(); // boolean
// Perform undo/redoconst undoSuccess = historyActions.undo(); // returns booleanconst redoSuccess = historyActions.redo(); // returns boolean
// Clear historyhistoryActions.clear(currentWorkflow);Transactions
Section titled “Transactions”Group multiple changes into a single undo step:
import { historyActions, workflowActions } from '@flowdrop/flowdrop/editor';
// Start a transactionhistoryActions.startTransaction(currentWorkflow, 'Rearrange layout');
// Make multiple changes — none are recorded individuallyworkflowActions.updateNode('node-1', { position: { x: 100, y: 200 } });workflowActions.updateNode('node-2', { position: { x: 300, y: 200 } });workflowActions.updateNode('node-3', { position: { x: 500, y: 200 } });
// Commit — all changes become one undo stephistoryActions.commitTransaction();
// Or cancel — all changes revert// historyActions.cancelTransaction();Building Custom Undo/Redo Buttons
Section titled “Building Custom Undo/Redo Buttons”import { getCanUndo, getCanRedo, historyActions } from '@flowdrop/flowdrop/editor';
// Create buttonsconst undoBtn = document.getElementById('undo');const redoBtn = document.getElementById('redo');
undoBtn.addEventListener('click', () => historyActions.undo());redoBtn.addEventListener('click', () => historyActions.redo());
// Update button state (polling — for non-Svelte frameworks)setInterval(() => { undoBtn.disabled = !getCanUndo(); redoBtn.disabled = !getCanRedo();}, 500);In Svelte, use reactivity instead of polling:
<script> import { getCanUndo, getCanRedo, historyActions } from '@flowdrop/flowdrop/editor'; const canUndo = $derived(getCanUndo()); const canRedo = $derived(getCanRedo());</script>
<button disabled={!canUndo} onclick={() => historyActions.undo()}>Undo</button><button disabled={!canRedo} onclick={() => historyActions.redo()}>Redo</button>Next Steps
Section titled “Next Steps”- Store System — all stores including history
- Event System —
onWorkflowChangefires after undo/redo