UNPKG

rich-text-editor

Version:
80 lines (79 loc) 3.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = useHistory; const react_1 = require("react"); function useHistory() { /** `stack` is an array with all the current history in order. * * `pointer` is a number that points to the current position in the history. * Undo lowers the pointer, redo makes it higher. * * Writing anything always clears the history stack above the pointer, adds a new value * and moves the pointer to the top of the stack. * */ const [stack, _setStack] = (0, react_1.useState)([]); const [pointer, _setPointer] = (0, react_1.useState)(0); /** Refs are needed to make the current value always accessible * in the handlers these will be ultimately called from. This is a bit convoluted * and prone to errors if the refs are not used and updated correctly, * so remember to always use the `set...` wrappers to update the state instead of * doing it directly. * */ const stackRef = (0, react_1.useRef)(stack); const pointerRef = (0, react_1.useRef)(pointer); const setStack = (newStack) => { stackRef.current = newStack; _setStack(newStack); }; const setPointer = (newPointer) => { pointerRef.current = newPointer; _setPointer(newPointer); }; const canUndo = pointer !== 0; const canRedo = pointer < stack.length - 1; const clear = () => { setStack([{ content: '' }]); setPointer(0); }; const write = (value, caretPositionBeforeChange, caretPositionAfterChange) => { const currentValue = stackRef.current.at(pointerRef.current); // If the pointer is at a value that's equal to the new value, // we don't do anything so we don't get duplicate values in the history if (value === (currentValue === null || currentValue === void 0 ? void 0 : currentValue.content)) return; const newEntry = { content: value, caretPositionBeforeChange: caretPositionBeforeChange, caretPositionAfterChange: caretPositionAfterChange, }; const newStack = [...stackRef.current.slice(0, pointerRef.current + 1), newEntry]; setStack(newStack); setPointer(newStack.length - 1); }; const undo = () => { var _a, _b, _c; const newPointer = pointerRef.current - 1; if (newPointer < 0) return undefined; const caretPosition = (_b = (_a = stackRef.current.at(pointerRef.current)) === null || _a === void 0 ? void 0 : _a.caretPositionBeforeChange) !== null && _b !== void 0 ? _b : 0; const newValue = stackRef.current.at(newPointer); setPointer(newPointer); return { content: (_c = newValue === null || newValue === void 0 ? void 0 : newValue.content) !== null && _c !== void 0 ? _c : '', newCaretPosition: caretPosition }; }; const redo = () => { const newPointer = pointerRef.current + 1; if (newPointer >= stackRef.current.length) return undefined; const newValue = stackRef.current.at(newPointer); setPointer(newPointer); return { content: newValue === null || newValue === void 0 ? void 0 : newValue.content, newCaretPosition: newValue === null || newValue === void 0 ? void 0 : newValue.caretPositionAfterChange }; }; return { canUndo, canRedo, write, clear, undo, redo, }; }