@leapfrog/interactive-canvas 1.10.2 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -294,6 +294,16 @@ export declare abstract class AbstractInteractiveCanvas implements IInteractiveC
294
294
  * @inheritDoc
295
295
  */
296
296
  createPNGStream(): any;
297
+ /**
298
+ * @override
299
+ * @inheritDoc
300
+ */
301
+ registerUndoState(): void;
302
+ /**
303
+ * @override
304
+ * @inheritDoc
305
+ */
306
+ undo(): Promise<void>;
297
307
  /**
298
308
  * Redraw the canvas.
299
309
  */
@@ -1,7 +1,19 @@
1
1
  import { AbstractInteractiveCanvas } from "./abstract-interactive-canvas";
2
2
  export declare class InteractiveCanvas extends AbstractInteractiveCanvas {
3
3
  protected devicePixelRatio: number;
4
+ private readonly undoStack;
5
+ private undoSub;
4
6
  constructor(elementId: string, devicePixelRatio: number);
7
+ /**
8
+ * @override
9
+ * @inheritDoc
10
+ */
11
+ registerUndoState(): void;
12
+ /**
13
+ * @override
14
+ * @inheritDoc
15
+ */
16
+ undo(): Promise<void>;
5
17
  private onFabricSelectionChanged;
6
18
  private enterTextSelectionModeIfRequired;
7
19
  private onTextEditing;
@@ -1,5 +1,5 @@
1
1
  import * as _ from 'lodash';
2
- import { round, each, values, reduce, clone, replace, find } from 'lodash';
2
+ import { round, each, values, reduce, clone, replace, find, isEqual } from 'lodash';
3
3
  import { oc } from 'ts-optchain';
4
4
  import { BehaviorSubject, Subject } from 'rxjs';
5
5
  import { fabric } from 'fabric';
@@ -3321,14 +3321,12 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3321
3321
  .value();
3322
3322
  var includedProperties = ["id"];
3323
3323
  var json = this.fabricCanvas.toJSON(includedProperties);
3324
- var state = {
3324
+ return {
3325
3325
  dimensions: this.dimensions$.value,
3326
3326
  canvasJson: JSON.stringify(json),
3327
3327
  objects: objects,
3328
3328
  backgroundColor: this.backgroundColor$.value
3329
3329
  };
3330
- console.debug("Saving canvas state", state);
3331
- return state;
3332
3330
  };
3333
3331
  /**
3334
3332
  * @override
@@ -3416,6 +3414,20 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3416
3414
  AbstractInteractiveCanvas.prototype.createPNGStream = function () {
3417
3415
  return this.fabricCanvas.createPNGStream();
3418
3416
  };
3417
+ /**
3418
+ * @override
3419
+ * @inheritDoc
3420
+ */
3421
+ AbstractInteractiveCanvas.prototype.registerUndoState = function () {
3422
+ throw Error("Undo not supported on this canvas type");
3423
+ };
3424
+ /**
3425
+ * @override
3426
+ * @inheritDoc
3427
+ */
3428
+ AbstractInteractiveCanvas.prototype.undo = function () {
3429
+ throw Error("Undo not supported on this canvas type");
3430
+ };
3419
3431
  /**
3420
3432
  * Redraw the canvas.
3421
3433
  */
@@ -3630,11 +3642,34 @@ var HeadlessInteractiveCanvas = /** @class */ (function (_super) {
3630
3642
  return HeadlessInteractiveCanvas;
3631
3643
  }(AbstractInteractiveCanvas));
3632
3644
 
3645
+ var UndoStack = /** @class */ (function () {
3646
+ function UndoStack(size) {
3647
+ this.stack = [];
3648
+ this.size = size;
3649
+ }
3650
+ UndoStack.prototype.push = function (state) {
3651
+ var prev = this.stack[this.stack.length - 1];
3652
+ if (isEqual(prev, state)) {
3653
+ console.error("Ignoring identical undo state"); //todo
3654
+ return;
3655
+ }
3656
+ console.error("Undo Registered"); //todo
3657
+ this.stack.push(state);
3658
+ if (this.stack.length > this.size)
3659
+ this.stack.splice(0, 1);
3660
+ };
3661
+ UndoStack.prototype.pop = function () {
3662
+ return this.stack.pop();
3663
+ };
3664
+ return UndoStack;
3665
+ }());
3666
+
3633
3667
  var InteractiveCanvas = /** @class */ (function (_super) {
3634
3668
  __extends(InteractiveCanvas, _super);
3635
3669
  function InteractiveCanvas(elementId, devicePixelRatio) {
3636
3670
  var _this = _super.call(this, window['fabric'], new window['fabric'].Canvas(elementId), devicePixelRatio) || this;
3637
3671
  _this.devicePixelRatio = devicePixelRatio;
3672
+ _this.undoStack = new UndoStack(10);
3638
3673
  //Initialize watchers
3639
3674
  _this.fabricCanvas.on("selection:updated", function () { return _this.onFabricSelectionChanged(); });
3640
3675
  _this.fabricCanvas.on("selection:created", function () { return _this.onFabricSelectionChanged(); });
@@ -3644,6 +3679,34 @@ var InteractiveCanvas = /** @class */ (function (_super) {
3644
3679
  _this.fabricCanvas.on("text:changed", function () { return _this.onTextChange(); });
3645
3680
  return _this;
3646
3681
  }
3682
+ /**
3683
+ * @override
3684
+ * @inheritDoc
3685
+ */
3686
+ InteractiveCanvas.prototype.registerUndoState = function () {
3687
+ this.undoStack.push(this.save());
3688
+ };
3689
+ /**
3690
+ * @override
3691
+ * @inheritDoc
3692
+ */
3693
+ InteractiveCanvas.prototype.undo = function () {
3694
+ return __awaiter(this, void 0, void 0, function () {
3695
+ var state;
3696
+ return __generator(this, function (_a) {
3697
+ switch (_a.label) {
3698
+ case 0:
3699
+ state = this.undoStack.pop();
3700
+ if (!state)
3701
+ return [2 /*return*/];
3702
+ return [4 /*yield*/, this.load(state)];
3703
+ case 1:
3704
+ _a.sent();
3705
+ return [2 /*return*/];
3706
+ }
3707
+ });
3708
+ });
3709
+ };
3647
3710
  InteractiveCanvas.prototype.onFabricSelectionChanged = function () {
3648
3711
  var selected = this.getFieldsByCanvasObject(this.fabricCanvas.getActiveObjects());
3649
3712
  console.debug("Selection changed", selected);
@@ -278,4 +278,12 @@ export interface IInteractiveCanvas {
278
278
  * Create a PNG stream of the canvas. Only works on headless canvas.
279
279
  */
280
280
  createPNGStream(): any;
281
+ /**
282
+ * Save the current state as an undo point.
283
+ */
284
+ registerUndoState(): void;
285
+ /**
286
+ * Revert the canvas state one entry.
287
+ */
288
+ undo(): Promise<void>;
281
289
  }
@@ -3321,14 +3321,12 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3321
3321
  .value();
3322
3322
  var includedProperties = ["id"];
3323
3323
  var json = this.fabricCanvas.toJSON(includedProperties);
3324
- var state = {
3324
+ return {
3325
3325
  dimensions: this.dimensions$.value,
3326
3326
  canvasJson: JSON.stringify(json),
3327
3327
  objects: objects,
3328
3328
  backgroundColor: this.backgroundColor$.value
3329
3329
  };
3330
- console.debug("Saving canvas state", state);
3331
- return state;
3332
3330
  };
3333
3331
  /**
3334
3332
  * @override
@@ -3416,6 +3414,20 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3416
3414
  AbstractInteractiveCanvas.prototype.createPNGStream = function () {
3417
3415
  return this.fabricCanvas.createPNGStream();
3418
3416
  };
3417
+ /**
3418
+ * @override
3419
+ * @inheritDoc
3420
+ */
3421
+ AbstractInteractiveCanvas.prototype.registerUndoState = function () {
3422
+ throw Error("Undo not supported on this canvas type");
3423
+ };
3424
+ /**
3425
+ * @override
3426
+ * @inheritDoc
3427
+ */
3428
+ AbstractInteractiveCanvas.prototype.undo = function () {
3429
+ throw Error("Undo not supported on this canvas type");
3430
+ };
3419
3431
  /**
3420
3432
  * Redraw the canvas.
3421
3433
  */
@@ -3630,11 +3642,34 @@ var HeadlessInteractiveCanvas = /** @class */ (function (_super) {
3630
3642
  return HeadlessInteractiveCanvas;
3631
3643
  }(AbstractInteractiveCanvas));
3632
3644
 
3645
+ var UndoStack = /** @class */ (function () {
3646
+ function UndoStack(size) {
3647
+ this.stack = [];
3648
+ this.size = size;
3649
+ }
3650
+ UndoStack.prototype.push = function (state) {
3651
+ var prev = this.stack[this.stack.length - 1];
3652
+ if (_.isEqual(prev, state)) {
3653
+ console.error("Ignoring identical undo state"); //todo
3654
+ return;
3655
+ }
3656
+ console.error("Undo Registered"); //todo
3657
+ this.stack.push(state);
3658
+ if (this.stack.length > this.size)
3659
+ this.stack.splice(0, 1);
3660
+ };
3661
+ UndoStack.prototype.pop = function () {
3662
+ return this.stack.pop();
3663
+ };
3664
+ return UndoStack;
3665
+ }());
3666
+
3633
3667
  var InteractiveCanvas = /** @class */ (function (_super) {
3634
3668
  __extends(InteractiveCanvas, _super);
3635
3669
  function InteractiveCanvas(elementId, devicePixelRatio) {
3636
3670
  var _this = _super.call(this, window['fabric'], new window['fabric'].Canvas(elementId), devicePixelRatio) || this;
3637
3671
  _this.devicePixelRatio = devicePixelRatio;
3672
+ _this.undoStack = new UndoStack(10);
3638
3673
  //Initialize watchers
3639
3674
  _this.fabricCanvas.on("selection:updated", function () { return _this.onFabricSelectionChanged(); });
3640
3675
  _this.fabricCanvas.on("selection:created", function () { return _this.onFabricSelectionChanged(); });
@@ -3644,6 +3679,34 @@ var InteractiveCanvas = /** @class */ (function (_super) {
3644
3679
  _this.fabricCanvas.on("text:changed", function () { return _this.onTextChange(); });
3645
3680
  return _this;
3646
3681
  }
3682
+ /**
3683
+ * @override
3684
+ * @inheritDoc
3685
+ */
3686
+ InteractiveCanvas.prototype.registerUndoState = function () {
3687
+ this.undoStack.push(this.save());
3688
+ };
3689
+ /**
3690
+ * @override
3691
+ * @inheritDoc
3692
+ */
3693
+ InteractiveCanvas.prototype.undo = function () {
3694
+ return __awaiter(this, void 0, void 0, function () {
3695
+ var state;
3696
+ return __generator(this, function (_a) {
3697
+ switch (_a.label) {
3698
+ case 0:
3699
+ state = this.undoStack.pop();
3700
+ if (!state)
3701
+ return [2 /*return*/];
3702
+ return [4 /*yield*/, this.load(state)];
3703
+ case 1:
3704
+ _a.sent();
3705
+ return [2 /*return*/];
3706
+ }
3707
+ });
3708
+ });
3709
+ };
3647
3710
  InteractiveCanvas.prototype.onFabricSelectionChanged = function () {
3648
3711
  var selected = this.getFieldsByCanvasObject(this.fabricCanvas.getActiveObjects());
3649
3712
  console.debug("Selection changed", selected);
@@ -0,0 +1,8 @@
1
+ import { ICanvasState } from "./types/canvas-state.interface";
2
+ export declare class UndoStack {
3
+ private readonly size;
4
+ private stack;
5
+ constructor(size: number);
6
+ push(state: ICanvasState): void;
7
+ pop(): ICanvasState;
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leapfrog/interactive-canvas",
3
- "version": "1.10.2",
3
+ "version": "1.11.0",
4
4
  "description": "Leapfrog interactive canvas",
5
5
  "files": [
6
6
  "dist"