UNPKG

jotai-history-global

Version:

Lightweight global undo/redo extension for Jotai. / 为 Jotai 提供全局撤销、重做功能的轻量扩展。

70 lines (69 loc) 2.46 kB
/** * 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); }