@sv-use/core
Version:
A collection of Svelte 5 utilities.
71 lines (70 loc) • 2.33 kB
JavaScript
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);
}
}
};
}