UNPKG

@sv-use/core

Version:

A collection of Svelte 5 utilities.

71 lines (70 loc) 2.33 kB
import { untrack } from 'svelte'; import { watch } from '../watch/index.svelte.js'; /** * Tracks the change history of a reactive value. * @param value The value to track. * @param set The setter function to update the value. * @param options Additional options to customize the behavior. * @see https://svelte-librarian.github.io/sv-use/docs/core/track-history */ export function trackHistory(value, set, options = {}) { const { includeCurrent = false } = options; let _redoHistory = $state([]); const _history = $state([]); let event = 'change'; watch(() => value(), (curr, prev) => { if (event === 'change') { untrack(() => { _history.push({ snapshot: includeCurrent ? curr : prev, timestamp: Date.now() }); _redoHistory = []; }); } else { event = 'change'; } }, { runOnMounted: includeCurrent }); return { get canUndo() { if (includeCurrent) { return _history.length > 1; } return _history.length > 0; }, get canRedo() { return _redoHistory.length > 0; }, get history() { return _history; }, get redoHistory() { return _redoHistory; }, undo() { if (includeCurrent) { if (_history.length >= 2) { const snapshot = _history.at(-2); _history.pop(); event = 'undo'; _redoHistory.push({ snapshot: value(), timestamp: Date.now() }); set(snapshot.snapshot); } } else { if (_history.length > 0) { const snapshot = _history.pop(); event = 'undo'; _redoHistory.push({ snapshot: value(), timestamp: Date.now() }); set(snapshot.snapshot); } } }, redo() { if (_redoHistory.length > 0) { const snapshot = _redoHistory.pop(); event = 'redo'; _history.push({ snapshot: value(), timestamp: Date.now() }); set(snapshot.snapshot); } } }; }