jotai-history-global
Version:
Lightweight global undo/redo extension for Jotai. / 为 Jotai 提供全局撤销、重做功能的轻量扩展。
70 lines (69 loc) • 2.46 kB
JavaScript
/**
* atomWithHistory
*
* Creates a Jotai atom that tracks its history for undo/redo operations
*/
import { atom } from 'jotai';
import { generateId, historyStore, isHistoryOperationInProgressAtom, pushToHistory, registerHistoryAtom } from './historyManager';
/**
* Creates an atom with history tracking
*
* @param initialValue - The initial value of the atom
* @param options - Configuration options
* @returns An atom that tracks its history
*/
export function atomWithHistory(initialValue, options = {}) {
// Generate a unique ID for this atom if not provided
const id = options.id || generateId();
const historyLimit = options.historyLimit;
const shouldTrack = options.shouldTrack || ((prev, next) => prev !== next);
// Handle custom diff function with type casting for compatibility
const customDiff = options.customDiff ?
((prev, next) => options.customDiff(prev, next)) : undefined;
const useFullValueInstead = options.useFullValueInstead;
// Create the base atom
const baseAtom = atom(initialValue);
// Create a writable atom that tracks history
const anAtom = atom(
// Getter
(get) => get(baseAtom),
// Setter
(get, set, update) => {
// Get current value before update
const prevValue = get(baseAtom);
const nextValue = update;
// Skip if the value hasn't changed according to the tracking function
if (!shouldTrack(prevValue, nextValue)) {
return;
}
// Skip recording history if we're in the middle of an undo/redo operation
const isHistoryOperation = get(isHistoryOperationInProgressAtom);
if (!isHistoryOperation) {
// Record the previous value in history using diff
pushToHistory(id, prevValue, nextValue, {
historyLimit,
customDiff,
useFullValueInstead
});
}
// Update the value
set(baseAtom, update);
});
// Attach the ID to the atom
anAtom.id = id;
// Register the atom with the history system
registerHistoryAtom(anAtom);
return anAtom;
}
/**
* Function to read an atom's value from the history store directly
*/
export function getAtomValue(atom) {
return historyStore.get(atom);
}
/**
* Function to set an atom's value in the history store directly
*/
export function setAtomValue(atom, value) {
historyStore.set(atom, value);
}