krona-front/src/features/settings/entities/useFormBuilderHistory.ts

79 lines
2.4 KiB
TypeScript

import { useState, useCallback, useEffect } from 'react';
import { LayoutDefinition } from '../../../services/contracts/metadata';
export function useFormBuilderHistory() {
const [currentLayout, setCurrentLayout] = useState<LayoutDefinition | null>(null);
const [isDirty, setIsDirty] = useState(false);
const [history, setHistory] = useState<LayoutDefinition[]>([]);
const [historyIndex, setHistoryIndex] = useState(-1);
const initHistory = useCallback((layout: LayoutDefinition) => {
setCurrentLayout(layout);
setHistory([layout]);
setHistoryIndex(0);
setIsDirty(false);
}, []);
const pushState = useCallback((newLayout: LayoutDefinition) => {
setHistory((prev) => {
const slice = prev.slice(0, historyIndex + 1);
const updated = [...slice, newLayout];
if (updated.length > 50) updated.shift();
return updated;
});
setHistoryIndex((prev) => Math.min(prev + 1, 49));
setCurrentLayout(newLayout);
setIsDirty(true);
}, [historyIndex]);
const handleUndo = useCallback(() => {
if (historyIndex > 0) {
const targetIndex = historyIndex - 1;
setHistoryIndex(targetIndex);
setCurrentLayout(history[targetIndex]);
setIsDirty(true);
}
}, [historyIndex, history]);
const handleRedo = useCallback(() => {
if (historyIndex < history.length - 1) {
const targetIndex = historyIndex + 1;
setHistoryIndex(targetIndex);
setCurrentLayout(history[targetIndex]);
setIsDirty(true);
}
}, [historyIndex, history]);
// Keyboard shortcut listener for Ctrl+Z and Ctrl+Y
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {
e.preventDefault();
handleUndo();
} else if (
((e.ctrlKey || e.metaKey) && e.key === 'y') ||
((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'z')
) {
e.preventDefault();
handleRedo();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [handleUndo, handleRedo]);
return {
currentLayout,
setCurrentLayout,
isDirty,
setIsDirty,
history,
historyIndex,
pushState,
handleUndo,
handleRedo,
initHistory,
canUndo: historyIndex > 0,
canRedo: historyIndex < history.length - 1,
};
}