History & Undo/Redo (HistoryPlugin)
createHistoryPlugin provides a complete operation history management system based on a pure snapshot stack. It supports Ctrl+Z / Ctrl+Y shortcuts and advanced time travel to jump directly to any historical step.
Quick Start
You can enable history management in two ways:
Method 1: Enable via Component Props (Recommended & Simplest)
You can set the history and max-history props directly on the <yh-flow> component. The component automatically registers and manages the history plugin internally, including keyboard shortcuts.
<template>
<yh-flow ref="flowRef" :history="true" :max-history="100" @history-change="handleHistoryChange" />
</template>
<script setup lang="ts">
const flowRef = ref()
const handleHistoryChange = ({ canUndo, canRedo }) => {
console.log('Can Undo:', canUndo, 'Can Redo:', canRedo)
}
// Methods are still accessible on flowRef
const undo = () => flowRef.value?.undo?.()
const redo = () => flowRef.value?.redo?.()
const saveSnapshot = () => flowRef.value?.saveSnapshot?.('Manual snapshot')
</script>Method 2: Manual Plugin Registration (Highly Customizable)
If you need advanced control or custom options, you can manually create and register the history plugin:
import { createHistoryPlugin } from '@yh-ui/flow'
onMounted(() => {
// 1. Create and install the history plugin
const plugin = createHistoryPlugin({
maxHistory: 100, // Keep up to 100 steps
enableKeyboard: true, // Bind Ctrl+Z / Ctrl+Y
onHistoryChange: (canUndo, canRedo, length) => {
// update UI states like disabled buttons
}
})
flowRef.value?.usePlugin(plugin)
})
// 2. Undo / Redo programmatically
const undo = () => flowRef.value?.undo?.()
const redo = () => flowRef.value?.redo?.()IMPORTANT
Whichever method you choose, the extended methods saveSnapshot, undo, redo, etc., are dynamically mounted to flowRef.value only after the component/plugin is loaded and ready. Ensure you call them inside onMounted or event/action callbacks.
Basic Usage Demo
API
HistoryPluginOptions
| Prop | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable plugin |
maxHistory | number | 100 | Maximum history steps |
enableKeyboard | boolean | true | Enable Ctrl+Z/Y global window shortcuts |
onHistoryChange | (canUndo, canRedo, length) => void | — | Callback on history change |
FlowInstance Extended Methods
Automatically mounted onto
flowRef.valueafterusePluginis called
| Method/Prop | Type | Description |
|---|---|---|
undo() | () => void | Undo to previous step |
redo() | () => void | Redo to next step |
saveSnapshot(desc?) | (description?: string) => void | Manually save current snapshot |
clearHistory() | () => void | Clear all history |
jumpToStep(index) | (index: number) => void | Jump to specific step (time travel) |
getHistory() | () => FlowHistorySnapshot[] | Get full history stack |
canUndo | Ref<boolean> | Whether undo is available (reactive) |
canRedo | Ref<boolean> | Whether redo is available (reactive) |
historyLength | Ref<number> | Total step count (reactive) |
FlowHistorySnapshot
interface FlowHistorySnapshot {
nodes: Node[]
edges: Edge[]
timestamp: number
description?: string
}Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Ctrl + Z / ⌘ + Z | Undo |
Ctrl + Y / ⌘ + Y | Redo |
Ctrl + Shift + Z / ⌘ + ⇧ + Z | Redo (macOS alternative) |
Best Practices
TIP
Manual snapshot saving is recommended over auto-capturing every tiny change. Calling saveSnapshot at key moments ensures meaningful steps for your users:
// ✅ Recommended: Save on drag complete
flowRef.value?.on('node:dragend', () => flowRef.value?.saveSnapshot?.('Drag node'))
// e.g. Call after connection established
// e.g. Call before bulk delete