import React, { createContext, useContext, useState, useCallback, useEffect } from 'react'; type UndoAction = { description: string; undoFn: () => void | Promise; }; type UndoStackContextType = { pushUndo: (action: UndoAction) => void; undo: () => void; stack: UndoAction[]; }; const UndoStackContext = createContext(undefined); export function UndoStackProvider({ children }: { children: React.ReactNode }) { const [stack, setStack] = useState([]); const pushUndo = useCallback((action: UndoAction) => { setStack((prev) => [...prev, action]); }, []); const undo = useCallback(async () => { setStack((prev) => { if (prev.length === 0) return prev; const lastAction = prev[prev.length - 1]; // Execute the undo function lastAction.undoFn(); return prev.slice(0, -1); }); }, []); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if ((e.ctrlKey || e.metaKey) && e.key === 'z') { e.preventDefault(); undo(); } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [undo]); return ( {children} ); } export function useUndoStack() { const context = useContext(UndoStackContext); if (!context) { throw new Error('useUndoStack must be used within an UndoStackProvider'); } return context; } export const UndoStack = () => { const { stack, undo } = useUndoStack(); if (stack.length === 0) return null; return (
Last action: {stack[stack.length - 1].description}
); };