https://github.com/elite174/solid-undo-redo
A list-based (O(1)) implementation of undo-redo for signals!
https://github.com/elite174/solid-undo-redo
history redo solidjs time-travel undo undo-redo
Last synced: 6 months ago
JSON representation
A list-based (O(1)) implementation of undo-redo for signals!
- Host: GitHub
- URL: https://github.com/elite174/solid-undo-redo
- Owner: elite174
- License: mit
- Created: 2023-04-10T10:04:15.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2023-09-14T01:34:57.000Z (about 2 years ago)
- Last Synced: 2024-03-15T06:46:39.804Z (over 1 year ago)
- Topics: history, redo, solidjs, time-travel, undo, undo-redo
- Language: TypeScript
- Homepage: https://solid-undo-redo.vercel.app
- Size: 259 KB
- Stars: 10
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# solid-undo-redo
[](https://www.npmjs.com/package/solid-undo-redo)
A small library for undo-redo operations!
Make signals with history.
The implementation is list-based, so it works in **O(1)** instead of O(n)!## Features
- Make `undo` or `redo` operations
- Set your history length
- React on undo and redo events with callbacks
- Turn your history into reactive iterator## Installation
`npm i solid-undo-redo`
`pnpm add solid-undo-redo`
`yarn add solid-undo-redo`
## Usage
```tsx
import { createSignalWithHistory } from "solid-undo-redo";const [value, setValue, history] = createSignalWithHistory(
undefined,
{ historyLength: 10 }
);setValue(1);
// Since we haven't provided the initial value (undefined)
// the history length equals to 1
console.assert(history.size() === 1);// Since the history length is 1
// we can't do undo and redo
console.assert(history.isUndoPossible() === false);
console.assert(history.isRedoPossible() === false);setValue(2);
// We added new value to the history
console.assert(history.size() === 2);// Now we can make undo operation
console.assert(history.isUndoPossible() === true);
// However we can't do redo because we're at the end
// of our history
console.assert(history.isRedoPossible() === false);// let's add some undo/redo listeners
history.registerCallback("undo", (currentValue, previousValue) =>
console.log(`Undo: ${currentValue}, ${previousValue}`)
);history.registerCallback("redo", (currentValue, previousValue) => {
console.log(`Redo: ${currentValue}, ${previousValue}`);
});// Don't forget to remove these listeners with api.removeCallback
// when you don't need them!history.undo();
// You'll see in the console "Undo: 1, 2"// Now we can't make undo operations
// because we're at the beginning of our history
console.assert(history.isUndoPossible() === false);
// But we can do redo!
console.assert(history.isRedoPossible() === true);history.redo();
// You'll see in the console "Redo: 2, 1"// Let's have a look at our history
console.log(history.toArray()); // [1, 2]// You can also use history.arraySignal
// To get a reactive accessor of the history array// Now let's clear our history and callbacks
history.dispose();
```## Docs
```tsx
function createSignalWithHistory(
initialValue?: T,
options?: SignalWithHistoryOptions
): SignalWithHistory;type CallbackTypeMap = {
undo: (currentValue: T, previousValue: T) => void;
redo: (currentValue: T, previousValue: T) => void;
};export interface SignalWithHistoryOptions {
/**
* Max history length
* @default 100
*/
historyLength?: number;
/**
* Solid signal options
*/
signalOptions?: SignalOptions | undefined;
}export type History = {
undo: VoidFunction;
redo: VoidFunction;/**
* Cleas the history
* @param clearCurrentValue - clears current value if set to true
* @default false
*/
clear: (clearCurrentValue?: boolean) => void;/** Reactive signal which indicates if undo operation is possible */
isUndoPossible: Accessor;
/** Reactive signal which indicates if redo operation is possible */
isRedoPossible: Accessor;/**
* Reactive generator function which is retriggered
* when the history changes
*/
createHistoryIterator: () => Generator;/**
* Reactive signal which shows the current history length
*/
size: Accessor;/** Register callback for undo/redo */
registerCallback: >(
type: CallbackType,
listener: CallbackTypeMap[CallbackType]
) => void;/** Remove callback for undo/redo */
removeCallback: >(
type: CallbackType,
listener: CallbackTypeMap[CallbackType]
) => void;/** Returns non-reactive history array */
toArray: () => Array;/** Reactive signal of history array */
arraySignal: Accessor>;/** Clear all registered callbacks and history */
dispose: VoidFunction;
};export type SignalWithHistory = [
/** Reactive accessor for the value */
get: Accessor,
/** Setter function for the value */
set: Setter,
history: History
];
```