An open API service indexing awesome lists of open source software.

https://github.com/anth0nycodes/fabric-history

A library built on top of fabric.js that allows for easy access to canvas history.
https://github.com/anth0nycodes/fabric-history

Last synced: 3 months ago
JSON representation

A library built on top of fabric.js that allows for easy access to canvas history.

Awesome Lists containing this project

README

          

# fabric-history

A library built on top of fabric.js that provides undo/redo history management for canvas operations.


GitHub Stars
NPM Downloads

## Features

- Undo/Redo functionality for fabric.js canvases
- Automatic history tracking for path creation, erasing events, object additions, removals, and modifications
- Multi-selection batching: operations on multiple selected objects are recorded as a single history entry
- Custom events for history state changes
- Fully type-safe
- Support for fabric.js v6 and v7

## Installation

```bash
npm install @anth0nycodes/fabric-history
```

or with pnpm:

```bash
pnpm add @anth0nycodes/fabric-history
```

or with yarn:

```bash
yarn add @anth0nycodes/fabric-history
```

## Usage

```typescript
import { CanvasWithHistory } from "@anth0nycodes/fabric-history";
import { Rect } from "fabric";

// Create a canvas with history support (same constructor as fabric.Canvas)
const canvas = new CanvasWithHistory("my-canvas", {
width: 800,
height: 600,
});

// Add objects - history is tracked automatically
const rect = new Rect({
left: 100,
top: 100,
width: 50,
height: 50,
fill: "red",
});
canvas.add(rect);

// Undo the last action
await canvas.undo();

// Redo the undone action
await canvas.redo();
```

### Using with `@erase2d/fabric`

To enable history tracking for erasing operations, use the `setEraserBrush` method with an `EraserBrush` from [`@erase2d/fabric`](https://github.com/erase2d/fabric). This ensures that erasing actions trigger the `erasing:end` event required for history tracking.

```typescript
import { CanvasWithHistory } from "@anth0nycodes/fabric-history";
import { EraserBrush } from "@erase2d/fabric";

const canvas = new CanvasWithHistory("my-canvas", {
width: 800,
height: 600,
});

// Create and set the eraser brush
const eraser = new EraserBrush(canvas);
eraser.width = 20;
canvas.setEraserBrush(eraser);

// Enable drawing mode to use the eraser
canvas.isDrawingMode = true;
```

## API

### `CanvasWithHistory`

Extends fabric.js `Canvas` class with history management capabilities.

#### Methods

| Method | Returns | Description |
| ------------------------ | --------------- | ---------------------------------------------------------------------------------------------------- |
| `undo()` | `Promise` | Undo the most recent action |
| `redo()` | `Promise` | Redo the most recently undone action |
| `canUndo()` | `boolean` | Check if an undo action is available |
| `canRedo()` | `boolean` | Check if a redo action is available |
| `setEraserBrush(eraser)` | `void` | Set an `EraserBrush` from `@erase2d/fabric` to enable history tracking for erasing operations |
| `clearHistory()` | `void` | Clear the undo and redo history stacks |
| `clearCanvas()` | `void` | Clear the canvas and save the cleared state to history (use this instead of the inherited `clear()`) |
| `dispose()` | `void` | Clean up event listeners and dispose the canvas |

#### Tracked Events

History is automatically saved when these fabric.js events occur:

- `path:created` - When a path is created (e.g., freehand drawing)
- `erasing:end` - When an erasing operation completes
- `object:added` - When an object is added to the canvas
- `object:removed` - When an object is removed from the canvas
- `object:modified` - When an object is modified (moved, scaled, rotated, etc.)

#### Custom Events

`CanvasWithHistory` fires custom events that you can listen to for history state changes:

| Event | Payload | Description |
| ----------------- | ------------------------------------ | --------------------------------- |
| `history:append` | `{ json: string, initial: boolean }` | Fired when a state is saved |
| `history:undo` | `{ lastUndoAction: string }` | Fired when an undo is performed |
| `history:redo` | `{ lastRedoAction: string }` | Fired when a redo is performed |
| `history:cleared` | `{}` | Fired when history stacks cleared |

**Example:**

```typescript
canvas.on("history:append", ({ json, initial }) => {
console.log("State saved:", initial ? "initial" : "action");
});

canvas.on("history:undo", ({ lastUndoAction }) => {
console.log("Undo performed");
});
```

## Requirements

- fabric.js 6.x or 7.x

## Development

```bash
# Install dependencies
pnpm install

# Run development server
pnpm dev

# Build the project
pnpm build

# Type check
pnpm check

# Run all tests
pnpm test

# Run integration tests only
pnpm test:it

# Run E2E tests only (uses Playwright)
pnpm test:e2e

# Run tests with coverage
pnpm coverage
```

## Contributing

Contributions are welcome! Please read our [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to submit pull requests.

## License

MIT

## Author

Anthony Hoang