@leapfrog/interactive-canvas 1.10.1 → 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
@@ -3354,6 +3352,7 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3354
3352
  case 2:
3355
3353
  if (canvasState.backgroundColor)
3356
3354
  this.setBackgroundColor(canvasState.backgroundColor);
3355
+ this.backgroundColor$.next(this.fabricCanvas.backgroundColor);
3357
3356
  this.bindFields(canvasState.objects);
3358
3357
  this.removePersistedBullets();
3359
3358
  this.layoutManager$.value.onInit();
@@ -3415,6 +3414,20 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3415
3414
  AbstractInteractiveCanvas.prototype.createPNGStream = function () {
3416
3415
  return this.fabricCanvas.createPNGStream();
3417
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
+ };
3418
3431
  /**
3419
3432
  * Redraw the canvas.
3420
3433
  */
@@ -3629,11 +3642,34 @@ var HeadlessInteractiveCanvas = /** @class */ (function (_super) {
3629
3642
  return HeadlessInteractiveCanvas;
3630
3643
  }(AbstractInteractiveCanvas));
3631
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
+
3632
3667
  var InteractiveCanvas = /** @class */ (function (_super) {
3633
3668
  __extends(InteractiveCanvas, _super);
3634
3669
  function InteractiveCanvas(elementId, devicePixelRatio) {
3635
3670
  var _this = _super.call(this, window['fabric'], new window['fabric'].Canvas(elementId), devicePixelRatio) || this;
3636
3671
  _this.devicePixelRatio = devicePixelRatio;
3672
+ _this.undoStack = new UndoStack(10);
3637
3673
  //Initialize watchers
3638
3674
  _this.fabricCanvas.on("selection:updated", function () { return _this.onFabricSelectionChanged(); });
3639
3675
  _this.fabricCanvas.on("selection:created", function () { return _this.onFabricSelectionChanged(); });
@@ -3643,6 +3679,34 @@ var InteractiveCanvas = /** @class */ (function (_super) {
3643
3679
  _this.fabricCanvas.on("text:changed", function () { return _this.onTextChange(); });
3644
3680
  return _this;
3645
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
+ };
3646
3710
  InteractiveCanvas.prototype.onFabricSelectionChanged = function () {
3647
3711
  var selected = this.getFieldsByCanvasObject(this.fabricCanvas.getActiveObjects());
3648
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
@@ -3354,6 +3352,7 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3354
3352
  case 2:
3355
3353
  if (canvasState.backgroundColor)
3356
3354
  this.setBackgroundColor(canvasState.backgroundColor);
3355
+ this.backgroundColor$.next(this.fabricCanvas.backgroundColor);
3357
3356
  this.bindFields(canvasState.objects);
3358
3357
  this.removePersistedBullets();
3359
3358
  this.layoutManager$.value.onInit();
@@ -3415,6 +3414,20 @@ var AbstractInteractiveCanvas = /** @class */ (function () {
3415
3414
  AbstractInteractiveCanvas.prototype.createPNGStream = function () {
3416
3415
  return this.fabricCanvas.createPNGStream();
3417
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
+ };
3418
3431
  /**
3419
3432
  * Redraw the canvas.
3420
3433
  */
@@ -3629,11 +3642,34 @@ var HeadlessInteractiveCanvas = /** @class */ (function (_super) {
3629
3642
  return HeadlessInteractiveCanvas;
3630
3643
  }(AbstractInteractiveCanvas));
3631
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
+
3632
3667
  var InteractiveCanvas = /** @class */ (function (_super) {
3633
3668
  __extends(InteractiveCanvas, _super);
3634
3669
  function InteractiveCanvas(elementId, devicePixelRatio) {
3635
3670
  var _this = _super.call(this, window['fabric'], new window['fabric'].Canvas(elementId), devicePixelRatio) || this;
3636
3671
  _this.devicePixelRatio = devicePixelRatio;
3672
+ _this.undoStack = new UndoStack(10);
3637
3673
  //Initialize watchers
3638
3674
  _this.fabricCanvas.on("selection:updated", function () { return _this.onFabricSelectionChanged(); });
3639
3675
  _this.fabricCanvas.on("selection:created", function () { return _this.onFabricSelectionChanged(); });
@@ -3643,6 +3679,34 @@ var InteractiveCanvas = /** @class */ (function (_super) {
3643
3679
  _this.fabricCanvas.on("text:changed", function () { return _this.onTextChange(); });
3644
3680
  return _this;
3645
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
+ };
3646
3710
  InteractiveCanvas.prototype.onFabricSelectionChanged = function () {
3647
3711
  var selected = this.getFieldsByCanvasObject(this.fabricCanvas.getActiveObjects());
3648
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.1",
3
+ "version": "1.11.0",
4
4
  "description": "Leapfrog interactive canvas",
5
5
  "files": [
6
6
  "dist"