import { useCallback, useEffect, useState } from "react"; export interface EditorState { content: string; isDirty: boolean; isSaving: boolean; lastSaved: Date | null; error: string | null; } export interface UseEditorStateOptions { initialContent?: string; autosaveDelay?: number; onSave?: (content: string) => Promise; onError?: (error: Error) => void; } export const useEditorState = ({ initialContent = "", autosaveDelay = 2000, onSave, onError, }: UseEditorStateOptions = {}) => { const [content, setContent] = useState(initialContent); const [isDirty, setIsDirty] = useState(false); const [isSaving, setIsSaving] = useState(false); const [lastSaved, setLastSaved] = useState(null); const [error, setError] = useState(null); const [autosaveTimeout, setAutosaveTimeout] = useState( null, ); const updateContent = useCallback((newContent: string) => { setContent(newContent); setIsDirty(true); setError(null); }, []); const save = useCallback(async () => { if (!onSave || !isDirty) return; setIsSaving(true); setError(null); try { await onSave(content); setIsDirty(false); setLastSaved(new Date()); } catch (err) { const errorMessage = err instanceof Error ? err.message : "Failed to save"; setError(errorMessage); onError?.(err instanceof Error ? err : new Error(errorMessage)); } finally { setIsSaving(false); } }, [content, isDirty, onSave, onError]); const reset = useCallback(() => { setContent(initialContent); setIsDirty(false); setError(null); }, [initialContent]); // Autosave useEffect(() => { if (!onSave || !isDirty || isSaving) return; if (autosaveTimeout) { clearTimeout(autosaveTimeout); } const timeout = setTimeout(() => { save(); }, autosaveDelay); setAutosaveTimeout(timeout); return () => { if (timeout) { clearTimeout(timeout); } }; }, [isDirty, isSaving, autosaveDelay, save, autosaveTimeout, onSave]); return { content, isDirty, isSaving, lastSaved, error, updateContent, save, reset, }; };