a tool for shared writing and social publishing
1import { UndoManager as RociUndoManager } from "@rocicorp/undo";
2import { create } from "zustand";
3
4export type UndoManager = ReturnType<typeof createUndoManager>;
5export const useUndoState = create(() => ({ canUndo: false, canRedo: false }));
6export const createUndoManager = () => {
7 let isGrouping = false;
8 let undoManager = new RociUndoManager({
9 onChange: (state) => {
10 useUndoState.setState(state);
11 },
12 });
13 let um = {
14 add: (args: {
15 undo: () => Promise<void> | void;
16 redo: () => Promise<void> | void;
17 }) => {
18 undoManager.add(args);
19 },
20 startGroup: (groupName?: string) => {
21 if (isGrouping) {
22 undoManager.endGroup();
23 }
24 isGrouping = true;
25 undoManager.startGroup();
26 },
27 endGroup: () => {
28 isGrouping = false;
29 undoManager.endGroup();
30 },
31 undo: () => undoManager.undo(),
32 redo: () => undoManager.redo(),
33 withUndoGroup: <T>(cb: () => T) => {
34 if (!isGrouping) um.startGroup();
35 const r = cb();
36 if (!isGrouping) um.endGroup();
37 return r;
38 },
39 };
40 return um;
41};