{"id":20192535,"url":"https://github.com/rocicorp/undo","last_synced_at":"2025-04-07T15:08:08.424Z","repository":{"id":43473798,"uuid":"507148393","full_name":"rocicorp/undo","owner":"rocicorp","description":"Undo Redo Manager","archived":false,"fork":false,"pushed_at":"2024-12-09T22:27:50.000Z","size":142,"stargazers_count":41,"open_issues_count":2,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-31T12:07:56.502Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rocicorp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-24T21:28:06.000Z","updated_at":"2025-03-10T09:23:19.000Z","dependencies_parsed_at":"2025-01-18T22:31:22.343Z","dependency_job_id":null,"html_url":"https://github.com/rocicorp/undo","commit_stats":{"total_commits":17,"total_committers":2,"mean_commits":8.5,"dds":"0.17647058823529416","last_synced_commit":"85a1d7b5412555b95670be180890ad028221fb5b"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocicorp%2Fundo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocicorp%2Fundo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocicorp%2Fundo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocicorp%2Fundo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rocicorp","download_url":"https://codeload.github.com/rocicorp/undo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247675597,"owners_count":20977376,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T04:00:59.580Z","updated_at":"2025-04-07T15:08:08.397Z","avatar_url":"https://github.com/rocicorp.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Undo\n\nA simple undo / redo manager. This was designed to work well with [Replicache](replicache.dev), but can be used entirely independently. From this library's perspective, undo/redo actions are just functions and this library doesn't care what those functions do. Please use [Replidraw](http://github.com/rocicorp/replidraw) as a reference on how to use the library.\n\n# Installation\n\n```\nnpm install @rocicorp/undo\n```\n\n# Replicache Usage Example\n\n```tsx\nimport { Replicache } from \"replicache\";\nimport { useSubscribe } from \"replicache-react\";\n...\nimport {UndoManager} from '@rocicorp/undo';\n\n// Replicache and UndoManager are initialized outside of the initial component render.\n// undoManager = new UndoManager()\nconst App = ({ rep }: { rep: Replicache\u003cM\u003e, undoManager: UndoManager }) =\u003e {\n  const todos = useSubscribe(rep, listTodos, [], [rep]);\n\n // new item with undo\n  const handleNewItem = (text: string) =\u003e {\n    const id = nanoid();\n    //function that will redo and execute\n    const putTodo = () =\u003e {\n      rep.mutate.putTodo({\n        id,\n        text: text,\n        sort: todos.length \u003e 0 ? todos[todos.length - 1].sort + 1 : 0,\n        completed: false,\n      });\n    };\n\n    //undo function\n    const removeTodo = () =\u003e rep.mutate.deleteTodos([id]);\n\n    undoManager.add({\n      execute: putTodo,\n      undo: removeTodo,\n    });\n  };\n\n  return (\n    \u003cdiv\u003e\n      \u003cHeader onNewItem={handleNewItem} /\u003e\n      \u003cMainSection\n        todos={todos}\n      /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n# Basic Usage Example\n\n```ts\nimport {UndoManager} from '@rocicorp/undo';\n\nconst undoManager = new UndoManager();\nconst modifiedValue = 0;\nundoManager.add({\n  undo: () =\u003e {\n    modifiedValue--;\n  },\n  execute: () =\u003e {\n    modifiedValue++;\n  },\n});\n```\n\n# API\n\n## \u003cb\u003econstructor\u003c/b\u003e\n\nConstructor for UndoManager\n\n| Param   | Type                             | Description                                 |\n| ------- | -------------------------------- | ------------------------------------------- |\n| options | \u003ccode\u003eUnderManagerOptions\u003c/code\u003e | Options passed for undo manager constructor |\n\nUnderManagerOptions\n\n| Param    | Type                                                   | Description                                                                       |\n| -------- | ------------------------------------------------------ | --------------------------------------------------------------------------------- |\n| maxSize  | \u003ccode\u003eObject\u003c/code\u003e                                    | The maximum number of entries in the stack. Default is 10000.                     |\n| onChange | \u003ccode\u003e(undoManager: UndoRedoStackState) =\u003e void\u003c/code\u003e | A callback function to be called when the stack canUndo or canRedo values change. |\n\n**Example**\n\n```ts\n   const undoManager = new UndoManager({ 10, (e: UndoRedoStackState) =\u003e {\n    console.log('undo manager canUndo or canRedo values changed -- ', e.canUndo, e.canRedo);\n   }});\n```\n\n---\n\n## \u003cb\u003ecanUndo\u003c/b\u003e\n\nDetermines if a user can perform the `undo` operation on the undoRedo stack.\n\n---\n\n## \u003cb\u003ecanRedo\u003c/b\u003e\n\nDetermines if a user can perform the `redo` operation on the undoRedo stack.\n\n---\n\n## \u003cb\u003eadd\u003c/b\u003e\n\nAdds an entry to the undoRedo stack.\n\n| Param   | Type                    | Description                                                                                                                                                              |\n| ------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| options | \u003ccode\u003eAddOptions\u003c/code\u003e | A `UndoRedo` or `ExecuteUndo` object that can is added to the stack. If it is an `ExecuteUndo` it will run the `execute` function immediately after adding to the stack. |\n\n### AddOptions\n\n```ts\ntype AddOptions = UndoRedo | ExecuteUndo;\n\ntype UndoRedo = {\n  redo: () =\u003e MaybePromise\u003cvoid\u003e;\n  undo: () =\u003e MaybePromise\u003cvoid\u003e;\n};\n\ntype ExecuteUndo = {\n  execute: () =\u003e MaybePromise\u003cvoid\u003e;\n  undo: () =\u003e MaybePromise\u003cvoid\u003e;\n};\n```\n\n---\n\n## \u003cb\u003eundo\u003c/b\u003e\n\nExecutes the undo function of the current entry in the undoRedo stack. If the current entry has groupID it will check the upcoming undo entry. If the upcoming undo entry also has the same `groupID` the function will recursively call undo until it runs into a entry that has has a different `groupID` or is `undefined`.\n\n---\n\n## \u003cb\u003eredo\u003c/b\u003e\n\nExecutes the redo function of the current entry in the undoRedo stack. If the current entry has groupID it will check the upcoming redo entry. If the upcoming redo entry also has the same `groupID` the function will recursively call redo until it runs into a entry that has has a different `groupID` or is `undefined`.\n\n---\n\n## \u003cb\u003estartGroup\u003c/b\u003e\n\nSets the undo manager to add `groupID` to all subsequent entries. Sets the `isGrouping` internal state of the stack to `true`\n\n---\n\n## \u003cb\u003eendGroup\u003c/b\u003e\n\nSets the undo manager to mark all subsequent added entries `groupID` to `undefined`. Sets the `isGrouping` internal state of the stack to `false`\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocicorp%2Fundo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frocicorp%2Fundo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocicorp%2Fundo/lists"}