UNPKG

resig.js

Version:

Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.

377 lines 30.7 kB
/** * Undo/Redo System * Uses Memento<State> with coalgebraic time-travel patterns */ import { signal, computed } from '../core/signal'; // Coalgebraic time-travel manager export class UndoRedoManager { constructor(initialState, config = {}) { this.config = config; this.lastCommand = null; this.mergeTimer = null; this.history = signal([this.createMemento(initialState, 'initial')]); this.future = signal([]); this.currentIndex = signal(0); this.currentState = signal(initialState); this.commands = signal([]); this.setupAutoMerge(); this.loadPersistedHistory(); } // Create memento snapshot (coalgebraic unfold) createMemento(state, id, metadata) { return { state: this.deepClone(state), timestamp: Date.now(), id, metadata, }; } // Deep clone state for immutability deepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; if (obj instanceof Date) return new Date(obj.getTime()); if (obj instanceof Array) return obj.map((item) => this.deepClone(item)); if (typeof obj === 'object') { const cloned = {}; Object.keys(obj).forEach((key) => { cloned[key] = this.deepClone(obj[key]); }); return cloned; } return obj; } // Setup automatic command merging setupAutoMerge() { if (!this.config.autoMerge) return; const mergeTimeout = this.config.mergeTimeout || 1000; this.commands.subscribe((commands) => { if (commands.length === 0) return; // const _lastCommand = commands[commands.length - 1]; // Unused for now if (this.mergeTimer) { clearTimeout(this.mergeTimer); } this.mergeTimer = window.setTimeout(() => { this.lastCommand = null; }, mergeTimeout); }); } // Load persisted history loadPersistedHistory() { if (!this.config.persistKey) return; try { const saved = localStorage.getItem(this.config.persistKey); if (saved) { const data = JSON.parse(saved); this.history._set(data.history || []); this.currentIndex._set(data.currentIndex || 0); const currentMemento = this.history.value()[this.currentIndex.value()]; if (currentMemento) { this.currentState._set(currentMemento.state); } } } catch (error) { console.warn('Failed to load persisted undo/redo history:', error); } } // Persist history persistHistory() { if (!this.config.persistKey) return; try { const data = { history: this.history.value(), currentIndex: this.currentIndex.value(), }; localStorage.setItem(this.config.persistKey, JSON.stringify(data)); } catch (error) { console.warn('Failed to persist undo/redo history:', error); } } // Compress history by removing intermediate states compressHistory() { if (!this.config.compressHistory) return; const maxSize = this.config.maxHistorySize || 50; const history = this.history.value(); if (history.length <= maxSize) return; // Keep first, last, and evenly distributed intermediate states const compressed = []; const step = Math.floor(history.length / maxSize); for (let i = 0; i < history.length; i += step) { compressed.push(history[i]); } // Always keep the last state if (compressed[compressed.length - 1] !== history[history.length - 1]) { compressed.push(history[history.length - 1]); } this.history._set(compressed); this.currentIndex._set(Math.min(this.currentIndex.value(), compressed.length - 1)); } // Execute command with coalgebraic time-travel execute(command) { const currentState = this.currentState.value(); // Try to merge with last command if auto-merge is enabled if (this.config.autoMerge && this.lastCommand) { if (command.canMerge?.(this.lastCommand)) { const mergedCommand = command.merge(this.lastCommand); this.executeInternal(mergedCommand, currentState); return; } } this.executeInternal(command, currentState); this.lastCommand = command; } // Internal command execution executeInternal(command, currentState) { try { const newState = command.execute(currentState); const memento = this.createMemento(newState, command.id, { commandName: command.name, commandId: command.id, }); // Clear future history (branching timeline) this.future._set([]); // Add to history const history = this.history.value(); const newHistory = [ ...history.slice(0, this.currentIndex.value() + 1), memento, ]; // Limit history size const maxSize = this.config.maxHistorySize || 50; if (newHistory.length > maxSize) { newHistory.splice(0, newHistory.length - maxSize); } this.history._set(newHistory); this.currentIndex._set(newHistory.length - 1); this.currentState._set(newState); // Add command to command history this.commands._set([...this.commands.value(), command]); // Compress history if needed this.compressHistory(); // Persist changes this.persistHistory(); } catch (error) { console.error('Failed to execute command:', error); } } // Undo operation (coalgebraic time-travel backward) undo() { const currentIdx = this.currentIndex.value(); const history = this.history.value(); if (currentIdx <= 0) return false; const previousMemento = history[currentIdx - 1]; const currentMemento = history[currentIdx]; // Move current state to future this.future._set([currentMemento, ...this.future.value()]); // Update current state this.currentIndex._set(currentIdx - 1); this.currentState._set(previousMemento.state); this.persistHistory(); return true; } // Redo operation (coalgebraic time-travel forward) redo() { const future = this.future.value(); if (future.length === 0) return false; const nextMemento = future[0]; const remainingFuture = future.slice(1); // Move state from future to history this.future._set(remainingFuture); this.currentIndex._set(this.currentIndex.value() + 1); this.currentState._set(nextMemento.state); this.persistHistory(); return true; } // Jump to specific point in history (coalgebraic time-travel to index) jumpTo(index) { const history = this.history.value(); if (index < 0 || index >= history.length) return false; const currentIdx = this.currentIndex.value(); const targetMemento = history[index]; if (index < currentIdx) { // Moving backward - add states to future const statesToFuture = history.slice(index + 1, currentIdx + 1).reverse(); this.future._set([...statesToFuture, ...this.future.value()]); } else if (index > currentIdx) { // Moving forward - remove states from future const statesToRemove = index - currentIdx; this.future._set(this.future.value().slice(statesToRemove)); } this.currentIndex._set(index); this.currentState._set(targetMemento.state); this.persistHistory(); return true; } // Create snapshot manually createSnapshot(id) { const currentState = this.currentState.value(); const memento = this.createMemento(currentState, id || `snapshot-${Date.now()}`, { type: 'manual-snapshot' }); const history = this.history.value(); const newHistory = [ ...history.slice(0, this.currentIndex.value() + 1), memento, ]; this.history._set(newHistory); this.currentIndex._set(newHistory.length - 1); this.future._set([]); this.persistHistory(); } // Get time-travel state getTimeTravel() { return computed(() => ({ currentIndex: this.currentIndex.value(), history: this.history.value(), future: this.future.value(), canUndo: this.currentIndex.value() > 0, canRedo: this.future.value().length > 0, totalStates: this.history.value().length + this.future.value().length, })); } // Get current state signal getCurrentState() { return this.currentState; } // Get history signal getHistory() { return this.history; } // Get commands signal getCommands() { return this.commands; } // Clear all history clearHistory() { const currentState = this.currentState.value(); const initialMemento = this.createMemento(currentState, 'reset'); this.history._set([initialMemento]); this.future._set([]); this.currentIndex._set(0); this.commands._set([]); this.persistHistory(); } // Get state at specific index getStateAt(index) { const history = this.history.value(); return history[index]?.state || null; } // Check if can undo/redo canUndo() { return this.currentIndex.value() > 0; } canRedo() { return this.future.value().length > 0; } // Cleanup destroy() { if (this.mergeTimer) { clearTimeout(this.mergeTimer); } } } // Factory function for creating undo/redo manager export const createUndoRedoManager = (initialState, config) => { return new UndoRedoManager(initialState, config); }; // Command builders export const createCommand = (id, name, execute, undo, options) => ({ id, name, timestamp: Date.now(), execute, undo, canMerge: options?.canMerge, merge: options?.merge, }); // Mergeable command for text editing export const createTextCommand = (id, type, position, text, previousText) => ({ id, name: `text-${type}`, timestamp: Date.now(), execute: (state) => { switch (type) { case 'insert': return state.slice(0, position) + text + state.slice(position); case 'delete': return state.slice(0, position) + state.slice(position + text.length); case 'replace': return (state.slice(0, position) + text + state.slice(position + (previousText?.length || 0))); default: return state; } }, undo: (state) => { switch (type) { case 'insert': return state.slice(0, position) + state.slice(position + text.length); case 'delete': return state.slice(0, position) + text + state.slice(position); case 'replace': return (state.slice(0, position) + (previousText || '') + state.slice(position + text.length)); default: return state; } }, canMerge: (other) => { return (other.name.startsWith('text-') && Math.abs(other.timestamp - Date.now()) < 1000); }, merge: (other) => { // Simplified merge logic - in production, implement proper text merging return createTextCommand(`${id}-${other.id}`, type, position, text, previousText); }, }); // Array manipulation commands export const createArrayCommand = (type, ...args) => ({ id: `array-${type}-${Date.now()}`, name: `array-${type}`, timestamp: Date.now(), execute: (state) => { const newState = [...state]; newState[type](...args); return newState; }, undo: (state) => { const newState = [...state]; // Implement reverse operations switch (type) { case 'push': newState.pop(); break; case 'pop': newState.push(args[0]); break; case 'shift': newState.unshift(args[0]); break; case 'unshift': newState.shift(); break; case 'splice': // Reverse splice operation const [start, deleteCount, ...items] = args; newState.splice(start, items.length, ...new Array(deleteCount)); break; } return newState; }, }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5kby1yZWRvLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2V4dGVuc2lvbnMvdW5kby1yZWRvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBVSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUF5QzFELGtDQUFrQztBQUNsQyxNQUFNLE9BQU8sZUFBZTtJQVMxQixZQUNFLFlBQWUsRUFDUCxTQUF5QixFQUFFO1FBQTNCLFdBQU0sR0FBTixNQUFNLENBQXFCO1FBTDdCLGdCQUFXLEdBQXNCLElBQUksQ0FBQztRQUN0QyxlQUFVLEdBQWtCLElBQUksQ0FBQztRQU12QyxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyRSxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN6QyxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUUzQixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELCtDQUErQztJQUN2QyxhQUFhLENBQ25CLEtBQVEsRUFDUixFQUFVLEVBQ1YsUUFBOEI7UUFFOUIsT0FBTztZQUNMLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQztZQUM1QixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNyQixFQUFFO1lBQ0YsUUFBUTtTQUNULENBQUM7SUFDSixDQUFD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