ngx-easy-image-drawing 0.0.26 → 0.0.28

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.
@@ -1,7 +1,8 @@
1
1
  import { Component, ViewChild, Input, Output, EventEmitter, } from "@angular/core";
2
2
  import * as i0 from "@angular/core";
3
3
  export class EasyImageDrawing {
4
- constructor() {
4
+ constructor(renderer) {
5
+ this.renderer = renderer;
5
6
  this.width = 500;
6
7
  this.height = 500;
7
8
  this.lineWidth = 7;
@@ -12,21 +13,18 @@ export class EasyImageDrawing {
12
13
  this.savedImage = new EventEmitter();
13
14
  this.previousPosition = { x: 0, y: 0 };
14
15
  this.activePath = false;
15
- this._mousedown = null;
16
- this._mousemove = null;
17
- this._mouseup = null;
18
- this._touchstart = null;
19
- this._touchmove = null;
20
- this._touchend = null;
21
- }
22
- ngOnChanges() {
23
- this._setCanvas();
16
+ this.eventListeners = [];
24
17
  }
25
18
  ngAfterViewInit() {
26
19
  this._setCanvas();
27
20
  this._setMouseEvents();
28
21
  this._setMouseEventsMobile();
29
22
  }
23
+ ngOnChanges(changes) {
24
+ if (changes["src"] && !changes["src"].firstChange) {
25
+ this.clear();
26
+ }
27
+ }
30
28
  save() {
31
29
  const dataUrl = this.canvas.nativeElement.toDataURL("image/png");
32
30
  const blob = this._dataURItoBlob(dataUrl);
@@ -71,7 +69,12 @@ export class EasyImageDrawing {
71
69
  return;
72
70
  this.canvas.nativeElement.width = this.width;
73
71
  this.canvas.nativeElement.height = this.height;
74
- this.context = this.canvas.nativeElement.getContext("2d");
72
+ const context = this.canvas.nativeElement.getContext("2d");
73
+ if (!context) {
74
+ console.error("Failed to get 2D context");
75
+ return;
76
+ }
77
+ this.context = context;
75
78
  this.context.lineWidth = this.lineWidth;
76
79
  this.context.strokeStyle = this.lineColor;
77
80
  this.context.lineCap = "round";
@@ -83,59 +86,53 @@ export class EasyImageDrawing {
83
86
  };
84
87
  }
85
88
  _setMouseEvents() {
86
- this._mousedown = window.addEventListener("mousedown", (event) => {
87
- this.activePath = true;
88
- this.context.beginPath();
89
- this.previousPosition = this.getPosition(event.clientX, event.clientY);
90
- });
91
- this._mousemove = window.addEventListener("mousemove", (event) => {
92
- if (this.activePath) {
93
- this._drawLine(event);
94
- }
95
- });
96
- this._mouseup = window.addEventListener("mouseup", () => {
97
- if (this.activePath) {
98
- this.context.closePath();
99
- this.activePath = false;
100
- }
101
- });
89
+ this.eventListeners.push(this.renderer.listen("window", "mousedown", this._onMouseDown.bind(this)), this.renderer.listen("window", "mousemove", this._onMouseMove.bind(this)), this.renderer.listen("window", "mouseup", this._onMouseUp.bind(this)));
90
+ }
91
+ _onMouseDown(event) {
92
+ this.activePath = true;
93
+ this.context.beginPath();
94
+ this.previousPosition = this.getPosition(event.clientX, event.clientY);
95
+ }
96
+ _onMouseMove(event) {
97
+ if (this.activePath) {
98
+ this._drawLine(event);
99
+ }
100
+ }
101
+ _onMouseUp() {
102
+ if (this.activePath) {
103
+ this.context.closePath();
104
+ this.activePath = false;
105
+ }
102
106
  }
103
107
  _setMouseEventsMobile() {
104
- this._touchstart = window.addEventListener("touchstart", (event) => {
105
- this.activePath = true;
106
- this.context.beginPath();
107
- this.previousPosition = this.getPosition(event.touches[0].clientX, event.touches[0].clientY);
108
- });
109
- this._touchmove = window.addEventListener("touchmove", (event) => {
110
- if (this.activePath) {
111
- this._drawLine(event.touches[0]);
112
- }
113
- });
114
- this._touchend = window.addEventListener("touchend", () => {
115
- if (this.activePath) {
116
- this.context.closePath();
117
- this.activePath = false;
118
- }
119
- });
120
- }
121
- _removeEventListeners() {
122
- window.removeEventListener("mousedown", this._mousedown);
123
- window.removeEventListener("mousemove", this._mousemove);
124
- window.removeEventListener("mouseup", this._mouseup);
125
- window.removeEventListener("touchstart", this._touchstart);
126
- window.removeEventListener("touchmove", this._touchmove);
127
- window.removeEventListener("touchend", this._touchend);
108
+ this.eventListeners.push(this.renderer.listen("window", "touchstart", this._onTouchStart.bind(this)), this.renderer.listen("window", "touchmove", this._onTouchMove.bind(this)), this.renderer.listen("window", "touchend", this._onTouchEnd.bind(this)));
109
+ }
110
+ _onTouchStart(event) {
111
+ this.activePath = true;
112
+ this.context.beginPath();
113
+ this.previousPosition = this.getPosition(event.touches[0].clientX, event.touches[0].clientY);
114
+ }
115
+ _onTouchMove(event) {
116
+ if (this.activePath) {
117
+ this._drawLine(event.touches[0]);
118
+ }
119
+ }
120
+ _onTouchEnd() {
121
+ if (this.activePath) {
122
+ this.context.closePath();
123
+ this.activePath = false;
124
+ }
128
125
  }
129
126
  ngOnDestroy() {
130
- this._removeEventListeners();
127
+ this.eventListeners.forEach((unlisten) => unlisten());
131
128
  }
132
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
129
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
133
130
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.3", type: EasyImageDrawing, isStandalone: true, selector: "easy-image-drawing", inputs: { width: "width", height: "height", lineWidth: "lineWidth", lineColor: "lineColor", src: "src", saveButtonColor: "saveButtonColor", undoButtonColor: "undoButtonColor" }, outputs: { savedImage: "savedImage" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["drawingCanvas"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}\n"] }); }
134
131
  }
135
132
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, decorators: [{
136
133
  type: Component,
137
134
  args: [{ selector: "easy-image-drawing", standalone: true, imports: [], template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}\n"] }]
138
- }], propDecorators: { width: [{
135
+ }], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { width: [{
139
136
  type: Input
140
137
  }], height: [{
141
138
  type: Input
@@ -155,4 +152,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImpor
155
152
  type: ViewChild,
156
153
  args: ["drawingCanvas"]
157
154
  }] } });
158
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWFzeS1pbWFnZS1kcmF3aW5nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LWltYWdlLWRyYXdpbmcvc3JjL2xpYi9lYXN5LWltYWdlLWRyYXdpbmcuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWVhc3ktaW1hZ2UtZHJhd2luZy9zcmMvbGliL2Vhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFNBQVMsRUFHVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksR0FHYixNQUFNLGVBQWUsQ0FBQzs7QUFTdkIsTUFBTSxPQUFPLGdCQUFnQjtJQVA3QjtRQVFXLFVBQUssR0FBVyxHQUFHLENBQUM7UUFDcEIsV0FBTSxHQUFXLEdBQUcsQ0FBQztRQUNyQixjQUFTLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsY0FBUyxHQUFHLFNBQVMsQ0FBQztRQUN0QixRQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ1Qsb0JBQWUsR0FBRyxTQUFTLENBQUM7UUFDNUIsb0JBQWUsR0FBRyxTQUFTLENBQUM7UUFDM0IsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFNeEMscUJBQWdCLEdBQTZCLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDNUQsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUVuQixlQUFVLEdBQVEsSUFBSSxDQUFDO1FBQ3ZCLGVBQVUsR0FBUSxJQUFJLENBQUM7UUFDdkIsYUFBUSxHQUFRLElBQUksQ0FBQztRQUVyQixnQkFBVyxHQUFRLElBQUksQ0FBQztRQUN4QixlQUFVLEdBQVEsSUFBSSxDQUFDO1FBQ3ZCLGNBQVMsR0FBUSxJQUFJLENBQUM7S0E2SS9CO0lBM0lDLFdBQVc7UUFDVCxJQUFJLENBQUMsVUFBVSxFQUFF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QUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzNELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7SUFDL0IsQ0FBQzs4R0FuS1UsZ0JBQWdCO2tHQUFoQixnQkFBZ0IscWFDbkI3Qix1ZkFxQkE7OzJGREZhLGdCQUFnQjtrQkFQNUIsU0FBUzsrQkFDRSxvQkFBb0IsY0FDbEIsSUFBSSxXQUNQLEVBQUU7OEJBS0YsS0FBSztzQkFBYixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csR0FBRztzQkFBWCxLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDSSxVQUFVO3NCQUFuQixNQUFNO2dCQUdxQixNQUFNO3NCQUFqQyxTQUFTO3VCQUFDLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBWaWV3Q2hpbGQsXHJcbiAgRWxlbWVudFJlZixcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIElucHV0LFxyXG4gIE91dHB1dCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgT25EZXN0cm95LFxyXG4gIE9uQ2hhbmdlcyxcclxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6IFwiZWFzeS1pbWFnZS1kcmF3aW5nXCIsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbXSxcclxuICB0ZW1wbGF0ZVVybDogXCIuL2Vhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuaHRtbFwiLFxyXG4gIHN0eWxlVXJsczogW1wiLi9lYXN5LWltYWdlLWRyYXdpbmcuY29tcG9uZW50LnNjc3NcIl0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBFYXN5SW1hZ2VEcmF3aW5nIGltcGxlbWVudHMgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xyXG4gIEBJbnB1dCgpIHdpZHRoOiBudW1iZXIgPSA1MDA7XHJcbiAgQElucHV0KCkgaGVpZ2h0OiBudW1iZXIgPSA1MDA7XHJcbiAgQElucHV0KCkgbGluZVdpZHRoID0gNztcclxuICBASW5wdXQoKSBsaW5lQ29sb3IgPSBcIiMwMDAwMDBcIjtcclxuICBASW5wdXQoKSBzcmMgPSBcIlwiO1xyXG4gIEBJbnB1dCgpIHNhdmVCdXR0b25Db2xvciA9IFwiIzRjYWY1MFwiO1xyXG4gIEBJbnB1dCgpIHVuZG9CdXR0b25Db2xvciA9IFwiI2Y0NDMzNlwiO1xyXG4gIEBPdXRwdXQoKSBzYXZlZEltYWdlID0gbmV3IEV2ZW50RW1pdHRlcjxGaWxlPigpO1xyXG5cclxuICAvLyBpdHMgaW1wb3J0YW50IG15Q2FudmFzIG1hdGNoZXMgdGhlIHZhcmlhYmxlIG5hbWUgaW4gdGhlIHRlbXBsYXRlXHJcbiAgQFZpZXdDaGlsZChcImRyYXdpbmdDYW52YXNcIikgY2FudmFzITogRWxlbWVudFJlZjxIVE1MQ2FudmFzRWxlbWVudD47XHJcblxyXG4gIGNvbnRleHQhOiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XHJcbiAgcHJpdmF0ZSBwcmV2aW91c1Bvc2l0aW9uOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0gPSB7IHg6IDAsIHk6IDAgfTtcclxuICBwcml2YXRlIGFjdGl2ZVBhdGggPSBmYWxzZTtcclxuXHJcbiAgcHJpdmF0ZSBfbW91c2Vkb3duOiBhbnkgPSBudWxsO1xyXG4gIHByaXZhdGUgX21vdXNlbW92ZTogYW55ID0gbnVsbDtcclxuICBwcml2YXRlIF9tb3VzZXVwOiBhbnkgPSBudWxsO1xyXG5cclxuICBwcml2YXRlIF90b3VjaHN0YXJ0OiBhbnkgPSBudWxsO1xyXG4gIHByaXZhdGUgX3RvdWNobW92ZTogYW55ID0gbnVsbDtcclxuICBwcml2YXRlIF90b3VjaGVuZDogYW55ID0gbnVsbDtcclxuXHJcbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9zZXRDYW52YXMoKTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuX3NldENhbnZhcygpO1xyXG4gICAgdGhpcy5fc2V0TW91c2VFdmVudHMoKTtcclxuICAgIHRoaXMuX3NldE1vdXNlRXZlbnRzTW9iaWxlKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2F2ZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGRhdGFVcmwgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LnRvRGF0YVVSTChcImltYWdlL3BuZ1wiKTtcclxuICAgIGNvbnN0IGJsb2IgPSB0aGlzLl9kYXRhVVJJdG9CbG9iKGRhdGFVcmwpO1xyXG4gICAgdGhpcy5zYXZlZEltYWdlLm5leHQobmV3IEZpbGUoW2Jsb2JdLCBcImltYWdlLnBuZ1wiKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY2xlYXIoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNvbnRleHQuY2xlYXJSZWN0KDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcclxuICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XHJcbiAgICBpbWFnZS5zcmMgPSB0aGlzLnNyYztcclxuICAgIGltYWdlLm9ubG9hZCA9ICgpID0+IHtcclxuICAgICAgdGhpcy5jb250ZXh0LmRyYXdJbWFnZShpbWFnZSwgMCwgMCwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2RhdGFVUkl0b0Jsb2IoZGF0YVVybDogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBieXRlU3RyaW5nID0gYXRvYihkYXRhVXJsLnNwbGl0KFwiLFwiKVsxXSk7XHJcbiAgICBjb25zdCBtaW1lU3RyaW5nID0gZGF0YVVybC5zcGxpdChcIixcIilbMF0uc3BsaXQoXCI6XCIpWzFdLnNwbGl0KFwiO1wiKVswXTtcclxuICAgIGNvbnN0IGFiID0gbmV3IEFycmF5QnVmZmVyKGJ5dGVTdHJpbmcubGVuZ3RoKTtcclxuICAgIGNvbnN0IGR3ID0gbmV3IERhdGFWaWV3KGFiKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZVN0cmluZy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBkdy5zZXRVaW50OChpLCBieXRlU3RyaW5nLmNoYXJDb2RlQXQoaSkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5ldyBCbG9iKFthYl0sIHsgdHlwZTogbWltZVN0cmluZyB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2RyYXdMaW5lKGV2ZW50OiBhbnkpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSk7XHJcbiAgICB0aGlzLmNvbnRleHQubW92ZVRvKHRoaXMucHJldmlvdXNQb3NpdGlvbi54LCB0aGlzLnByZXZpb3VzUG9zaXRpb24ueSk7XHJcbiAgICB0aGlzLmNvbnRleHQubGluZVRvKGN1cnJlbnRQb3NpdGlvbi54LCBjdXJyZW50UG9zaXRpb24ueSk7XHJcbiAgICB0aGlzLnByZXZpb3VzUG9zaXRpb24gPSBjdXJyZW50UG9zaXRpb247XHJcbiAgICB0aGlzLmNvbnRleHQuc3Ryb2tlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldFBvc2l0aW9uKFxyXG4gICAgY2xpZW50WDogbnVtYmVyLFxyXG4gICAgY2xpZW50WTogbnVtYmVyXHJcbiAgKTogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHtcclxuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3Qgc2NhbGVYID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC53aWR0aCAvIHJlY3Qud2lkdGg7XHJcbiAgICBjb25zdCBzY2FsZVkgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmhlaWdodCAvIHJlY3QuaGVpZ2h0O1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgeDogKGNsaWVudFggLSByZWN0LmxlZnQpICogc2NhbGVYLFxyXG4gICAgICB5OiAoY2xpZW50WSAtIHJlY3QudG9wKSAqIHNjYWxlWSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9zZXRDYW52YXMoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY2FudmFzKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC53aWR0aCA9IHRoaXMud2lkdGg7XHJcbiAgICB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmhlaWdodCA9IHRoaXMuaGVpZ2h0O1xyXG5cclxuICAgIHRoaXMuY29udGV4dCA9IHRoaXMuY2FudmFzLm5hdGl2ZUVsZW1lbnQuZ2V0Q29udGV4dChcIjJkXCIpITtcclxuICAgIHRoaXMuY29udGV4dC5saW5lV2lkdGggPSB0aGlzLmxpbmVXaWR0aDtcclxuICAgIHRoaXMuY29udGV4dC5zdHJva2VTdHlsZSA9IHRoaXMubGluZUNvbG9yO1xyXG4gICAgdGhpcy5jb250ZXh0LmxpbmVDYXAgPSBcInJvdW5kXCI7XHJcblxyXG4gICAgLy8gc2V0IHNyYyB0byBpbWFnZVxyXG4gICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcclxuICAgIGltYWdlLnNyYyA9IHRoaXMuc3JjO1xyXG4gICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICB0aGlzLmNvbnRleHQuZHJhd0ltYWdlKGltYWdlLCAwLCAwLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfc2V0TW91c2VFdmVudHMoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9tb3VzZWRvd24gPSB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcclxuICAgICAgXCJtb3VzZWRvd25cIixcclxuICAgICAgKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB7XHJcbiAgICAgICAgdGhpcy5hY3RpdmVQYXRoID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmNvbnRleHQuYmVnaW5QYXRoKCk7XHJcbiAgICAgICAgdGhpcy5wcmV2aW91c1Bvc2l0aW9uID0gdGhpcy5nZXRQb3NpdGlvbihldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZKTtcclxuICAgICAgfVxyXG4gICAgKTtcclxuXHJcbiAgICB0aGlzLl9tb3VzZW1vdmUgPSB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlbW92ZVwiLCAoZXZlbnQpID0+IHtcclxuICAgICAgaWYgKHRoaXMuYWN0aXZlUGF0aCkge1xyXG4gICAgICAgIHRoaXMuX2RyYXdMaW5lKGV2ZW50KTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5fbW91c2V1cCA9IHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwibW91c2V1cFwiLCAoKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLmFjdGl2ZVBhdGgpIHtcclxuICAgICAgICB0aGlzLmNvbnRleHQuY2xvc2VQYXRoKCk7XHJcbiAgICAgICAgdGhpcy5hY3RpdmVQYXRoID0gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfc2V0TW91c2VFdmVudHNNb2JpbGUoKTogdm9pZCB7XHJcbiAgICB0aGlzLl90b3VjaHN0YXJ0ID0gd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXHJcbiAgICAgIFwidG91Y2hzdGFydFwiLFxyXG4gICAgICAoZXZlbnQ6IFRvdWNoRXZlbnQpID0+IHtcclxuICAgICAgICB0aGlzLmFjdGl2ZVBhdGggPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuY29udGV4dC5iZWdpblBhdGgoKTtcclxuICAgICAgICB0aGlzLnByZXZpb3VzUG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uKFxyXG4gICAgICAgICAgZXZlbnQudG91Y2hlc1swXS5jbGllbnRYLFxyXG4gICAgICAgICAgZXZlbnQudG91Y2hlc1swXS5jbGllbnRZXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgKTtcclxuXHJcbiAgICB0aGlzLl90b3VjaG1vdmUgPSB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInRvdWNobW92ZVwiLCAoZXZlbnQpID0+IHtcclxuICAgICAgaWYgKHRoaXMuYWN0aXZlUGF0aCkge1xyXG4gICAgICAgIHRoaXMuX2RyYXdMaW5lKGV2ZW50LnRvdWNoZXNbMF0pO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLl90b3VjaGVuZCA9IHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwidG91Y2hlbmRcIiwgKCkgPT4ge1xyXG4gICAgICBpZiAodGhpcy5hY3RpdmVQYXRoKSB7XHJcbiAgICAgICAgdGhpcy5jb250ZXh0LmNsb3NlUGF0aCgpO1xyXG4gICAgICAgIHRoaXMuYWN0aXZlUGF0aCA9IGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX3JlbW92ZUV2ZW50TGlzdGVuZXJzKCk6IHZvaWQge1xyXG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZWRvd25cIiwgdGhpcy5fbW91c2Vkb3duKTtcclxuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsIHRoaXMuX21vdXNlbW92ZSk7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIiwgdGhpcy5fbW91c2V1cCk7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInRvdWNoc3RhcnRcIiwgdGhpcy5fdG91Y2hzdGFydCk7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInRvdWNobW92ZVwiLCB0aGlzLl90b3VjaG1vdmUpO1xyXG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJ0b3VjaGVuZFwiLCB0aGlzLl90b3VjaGVuZCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuX3JlbW92ZUV2ZW50TGlzdGVuZXJzKCk7XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJjYW52YXMtd3JhcHBlclwiPlxyXG4gIDxjYW52YXMgaWQ9XCJjYW52YXNcIiAjZHJhd2luZ0NhbnZhcz48L2NhbnZhcz5cclxuPC9kaXY+XHJcbjxkaXYgY2xhc3M9XCJpbWFnZS1idXR0b24td3JhcHBlclwiPlxyXG4gIDxidXR0b25cclxuICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgKGNsaWNrKT1cInNhdmUoKVwiXHJcbiAgICBjbGFzcz1cImJ1dHRvbiBzYXZlXCJcclxuICAgIFtzdHlsZS5iYWNrZ3JvdW5kLWNvbG9yXT1cInNhdmVCdXR0b25Db2xvclwiXHJcbiAgPlxyXG4gICAgU2F2ZVxyXG4gIDwvYnV0dG9uPlxyXG4gIDxidXR0b25cclxuICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgKGNsaWNrKT1cImNsZWFyKClcIlxyXG4gICAgY2xhc3M9XCJidXR0b24gdW5kb1wiXHJcbiAgICBbc3R5bGUuYmFja2dyb3VuZC1jb2xvcl09XCJ1bmRvQnV0dG9uQ29sb3JcIlxyXG4gID5cclxuICAgIFVuZG9cclxuICA8L2J1dHRvbj5cclxuPC9kaXY+XHJcbiJdfQ==
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWFzeS1pbWFnZS1kcmF3aW5nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LWltYWdlLWRyYXdpbmcvc3JjL2xpYi9lYXN5LWltYWdlLWRyYXdpbmcuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWVhc3ktaW1hZ2UtZHJhd2luZy9zcmMvbGliL2Vhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFNBQVMsRUFHVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksR0FLYixNQUFNLGVBQWUsQ0FBQzs7QUFTdkIsTUFBTSxPQUFPLGdCQUFnQjtJQWtCM0IsWUFBb0IsUUFBbUI7UUFBbkIsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQWpCOUIsVUFBSyxHQUFXLEdBQUcsQ0FBQztRQUNwQixXQUFNLEdBQVcsR0FBRyxDQUFDO1FBQ3JCLGNBQVMsR0FBVyxDQUFDLENBQUM7UUFDdEIsY0FBUyxHQUFHLFNBQVMsQ0FBQztRQUN0QixRQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ1Qsb0JBQWUsR0FBRyxTQUFTLENBQUM7UUFDNUIsb0JBQWUsR0FBRyxTQUFTLENBQUM7UUFDM0IsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFNeEMscUJBQWdCLEdBQTZCLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDNUQsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUNuQixtQkFBYyxHQUFtQixFQUFFLENBQUM7SUFFRixDQUFDO0lBRTNDLGVBQWU7UUFDYixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFF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Q0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQztJQUVPLFdBQVc7UUFDakIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUMxQixDQUFDO0lBQ0gsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUN4RCxDQUFDOzhHQXJLVSxnQkFBZ0I7a0dBQWhCLGdCQUFnQixxYUNyQjdCLHVmQXFCQTs7MkZEQWEsZ0JBQWdCO2tCQVA1QixTQUFTOytCQUNFLG9CQUFvQixjQUNsQixJQUFJLFdBQ1AsRUFBRTs4RUFLRixLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxHQUFHO3NCQUFYLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNJLFVBQVU7c0JBQW5CLE1BQU07Z0JBR3FCLE1BQU07c0JBQWpDLFNBQVM7dUJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIFZpZXdDaGlsZCxcclxuICBFbGVtZW50UmVmLFxyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgSW5wdXQsXHJcbiAgT3V0cHV0LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBPbkRlc3Ryb3ksXHJcbiAgT25DaGFuZ2VzLFxyXG4gIFJlbmRlcmVyMixcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogXCJlYXN5LWltYWdlLWRyYXdpbmdcIixcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtdLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4vZWFzeS1pbWFnZS1kcmF3aW5nLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgc3R5bGVVcmxzOiBbXCIuL2Vhc3ktaW1hZ2UtZHJhd2luZy5jb21wb25lbnQuc2Nzc1wiXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIEVhc3lJbWFnZURyYXdpbmcgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgQElucHV0KCkgd2lkdGg6IG51bWJlciA9IDUwMDtcclxuICBASW5wdXQoKSBoZWlnaHQ6IG51bWJlciA9IDUwMDtcclxuICBASW5wdXQoKSBsaW5lV2lkdGg6IG51bWJlciA9IDc7XHJcbiAgQElucHV0KCkgbGluZUNvbG9yID0gXCIjMDAwMDAwXCI7XHJcbiAgQElucHV0KCkgc3JjID0gXCJcIjtcclxuICBASW5wdXQoKSBzYXZlQnV0dG9uQ29sb3IgPSBcIiM0Y2FmNTBcIjtcclxuICBASW5wdXQoKSB1bmRvQnV0dG9uQ29sb3IgPSBcIiNmNDQzMzZcIjtcclxuICBAT3V0cHV0KCkgc2F2ZWRJbWFnZSA9IG5ldyBFdmVudEVtaXR0ZXI8RmlsZT4oKTtcclxuXHJcbiAgLy8gaXRzIGltcG9ydGFudCBteUNhbnZhcyBtYXRjaGVzIHRoZSB2YXJpYWJsZSBuYW1lIGluIHRoZSB0ZW1wbGF0ZVxyXG4gIEBWaWV3Q2hpbGQoXCJkcmF3aW5nQ2FudmFzXCIpIGNhbnZhcyE6IEVsZW1lbnRSZWY8SFRNTENhbnZhc0VsZW1lbnQ+O1xyXG5cclxuICBjb250ZXh0ITogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xyXG4gIHByaXZhdGUgcHJldmlvdXNQb3NpdGlvbjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9ID0geyB4OiAwLCB5OiAwIH07XHJcbiAgcHJpdmF0ZSBhY3RpdmVQYXRoID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBldmVudExpc3RlbmVyczogKCgpID0+IHZvaWQpW10gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyKSB7fVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9zZXRDYW52YXMoKTtcclxuICAgIHRoaXMuX3NldE1vdXNlRXZlbnRzKCk7XHJcbiAgICB0aGlzLl9zZXRNb3VzZUV2ZW50c01vYmlsZSgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKGNoYW5nZXNbXCJzcmNcIl0gJiYgIWNoYW5nZXNbXCJzcmNcIl0uZmlyc3RDaGFuZ2UpIHtcclxuICAgICAgdGhpcy5jbGVhcigpO1xyXG4gICAgfVxyXG4gIH1cclxuICBwdWJsaWMgc2F2ZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGRhdGFVcmwgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LnRvRGF0YVVSTChcImltYWdlL3BuZ1wiKTtcclxuICAgIGNvbnN0IGJsb2IgPSB0aGlzLl9kYXRhVVJJdG9CbG9iKGRhdGFVcmwpO1xyXG4gICAgdGhpcy5zYXZlZEltYWdlLm5leHQobmV3IEZpbGUoW2Jsb2JdLCBcImltYWdlLnBuZ1wiKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY2xlYXIoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNvbnRleHQuY2xlYXJSZWN0KDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcclxuICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XHJcbiAgICBpbWFnZS5zcmMgPSB0aGlzLnNyYztcclxuICAgIGltYWdlLm9ubG9hZCA9ICgpID0+IHtcclxuICAgICAgdGhpcy5jb250ZXh0LmRyYXdJbWFnZShpbWFnZSwgMCwgMCwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHQpO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2RhdGFVUkl0b0Jsb2IoZGF0YVVybDogc3RyaW5nKSB7XHJcbiAgICBjb25zdCBieXRlU3RyaW5nID0gYXRvYihkYXRhVXJsLnNwbGl0KFwiLFwiKVsxXSk7XHJcbiAgICBjb25zdCBtaW1lU3RyaW5nID0gZGF0YVVybC5zcGxpdChcIixcIilbMF0uc3BsaXQoXCI6XCIpWzFdLnNwbGl0KFwiO1wiKVswXTtcclxuICAgIGNvbnN0IGFiID0gbmV3IEFycmF5QnVmZmVyKGJ5dGVTdHJpbmcubGVuZ3RoKTtcclxuICAgIGNvbnN0IGR3ID0gbmV3IERhdGFWaWV3KGFiKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZVN0cmluZy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBkdy5zZXRVaW50OChpLCBieXRlU3RyaW5nLmNoYXJDb2RlQXQoaSkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5ldyBCbG9iKFthYl0sIHsgdHlwZTogbWltZVN0cmluZyB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2RyYXdMaW5lKGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2gpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSk7XHJcbiAgICB0aGlzLmNvbnRleHQubW92ZVRvKHRoaXMucHJldmlvdXNQb3NpdGlvbi54LCB0aGlzLnByZXZpb3VzUG9zaXRpb24ueSk7XHJcbiAgICB0aGlzLmNvbnRleHQubGluZVRvKGN1cnJlbnRQb3NpdGlvbi54LCBjdXJyZW50UG9zaXRpb24ueSk7XHJcbiAgICB0aGlzLnByZXZpb3VzUG9zaXRpb24gPSBjdXJyZW50UG9zaXRpb247XHJcbiAgICB0aGlzLmNvbnRleHQuc3Ryb2tlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldFBvc2l0aW9uKFxyXG4gICAgY2xpZW50WDogbnVtYmVyLFxyXG4gICAgY2xpZW50WTogbnVtYmVyXHJcbiAgKTogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHtcclxuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3Qgc2NhbGVYID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC53aWR0aCAvIHJlY3Qud2lkdGg7XHJcbiAgICBjb25zdCBzY2FsZVkgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmhlaWdodCAvIHJlY3QuaGVpZ2h0O1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgeDogKGNsaWVudFggLSByZWN0LmxlZnQpICogc2NhbGVYLFxyXG4gICAgICB5OiAoY2xpZW50WSAtIHJlY3QudG9wKSAqIHNjYWxlWSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9zZXRDYW52YXMoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY2FudmFzKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudC53aWR0aCA9IHRoaXMud2lkdGg7XHJcbiAgICB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmhlaWdodCA9IHRoaXMuaGVpZ2h0O1xyXG5cclxuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50LmdldENvbnRleHQoXCIyZFwiKTtcclxuICAgIGlmICghY29udGV4dCkge1xyXG4gICAgICBjb25zb2xlLmVycm9yKFwiRmFpbGVkIHRvIGdldCAyRCBjb250ZXh0XCIpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xyXG4gICAgdGhpcy5jb250ZXh0LmxpbmVXaWR0aCA9IHRoaXMubGluZVdpZHRoO1xyXG4gICAgdGhpcy5jb250ZXh0LnN0cm9rZVN0eWxlID0gdGhpcy5saW5lQ29sb3I7XHJcbiAgICB0aGlzLmNvbnRleHQubGluZUNhcCA9IFwicm91bmRcIjtcclxuXHJcbiAgICAvLyBzZXQgc3JjIHRvIGltYWdlXHJcbiAgICBjb25zdCBpbWFnZSA9IG5ldyBJbWFnZSgpO1xyXG4gICAgaW1hZ2Uuc3JjID0gdGhpcy5zcmM7XHJcbiAgICBpbWFnZS5vbmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgIHRoaXMuY29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0KTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9zZXRNb3VzZUV2ZW50cygpOiB2b2lkIHtcclxuICAgIHRoaXMuZXZlbnRMaXN0ZW5lcnMucHVzaChcclxuICAgICAgdGhpcy5yZW5kZXJlci5saXN0ZW4oXCJ3aW5kb3dcIiwgXCJtb3VzZWRvd25cIiwgdGhpcy5fb25Nb3VzZURvd24uYmluZCh0aGlzKSksXHJcbiAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFwid2luZG93XCIsIFwibW91c2Vtb3ZlXCIsIHRoaXMuX29uTW91c2VNb3ZlLmJpbmQodGhpcykpLFxyXG4gICAgICB0aGlzLnJlbmRlcmVyLmxpc3RlbihcIndpbmRvd1wiLCBcIm1vdXNldXBcIiwgdGhpcy5fb25Nb3VzZVVwLmJpbmQodGhpcykpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Nb3VzZURvd24oZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgIHRoaXMuYWN0aXZlUGF0aCA9IHRydWU7XHJcbiAgICB0aGlzLmNvbnRleHQuYmVnaW5QYXRoKCk7XHJcbiAgICB0aGlzLnByZXZpb3VzUG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uKGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Nb3VzZU1vdmUoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmFjdGl2ZVBhdGgpIHtcclxuICAgICAgdGhpcy5fZHJhd0xpbmUoZXZlbnQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Nb3VzZVVwKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuYWN0aXZlUGF0aCkge1xyXG4gICAgICB0aGlzLmNvbnRleHQuY2xvc2VQYXRoKCk7XHJcbiAgICAgIHRoaXMuYWN0aXZlUGF0aCA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfc2V0TW91c2VFdmVudHNNb2JpbGUoKTogdm9pZCB7XHJcbiAgICB0aGlzLmV2ZW50TGlzdGVuZXJzLnB1c2goXHJcbiAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFxyXG4gICAgICAgIFwid2luZG93XCIsXHJcbiAgICAgICAgXCJ0b3VjaHN0YXJ0XCIsXHJcbiAgICAgICAgdGhpcy5fb25Ub3VjaFN0YXJ0LmJpbmQodGhpcylcclxuICAgICAgKSxcclxuICAgICAgdGhpcy5yZW5kZXJlci5saXN0ZW4oXCJ3aW5kb3dcIiwgXCJ0b3VjaG1vdmVcIiwgdGhpcy5fb25Ub3VjaE1vdmUuYmluZCh0aGlzKSksXHJcbiAgICAgIHRoaXMucmVuZGVyZXIubGlzdGVuKFwid2luZG93XCIsIFwidG91Y2hlbmRcIiwgdGhpcy5fb25Ub3VjaEVuZC5iaW5kKHRoaXMpKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX29uVG91Y2hTdGFydChldmVudDogVG91Y2hFdmVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5hY3RpdmVQYXRoID0gdHJ1ZTtcclxuICAgIHRoaXMuY29udGV4dC5iZWdpblBhdGgoKTtcclxuICAgIHRoaXMucHJldmlvdXNQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oXHJcbiAgICAgIGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WCxcclxuICAgICAgZXZlbnQudG91Y2hlc1swXS5jbGllbnRZXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfb25Ub3VjaE1vdmUoZXZlbnQ6IFRvdWNoRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmFjdGl2ZVBhdGgpIHtcclxuICAgICAgdGhpcy5fZHJhd0xpbmUoZXZlbnQudG91Y2hlc1swXSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9vblRvdWNoRW5kKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuYWN0aXZlUGF0aCkge1xyXG4gICAgICB0aGlzLmNvbnRleHQuY2xvc2VQYXRoKCk7XHJcbiAgICAgIHRoaXMuYWN0aXZlUGF0aCA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmV2ZW50TGlzdGVuZXJzLmZvckVhY2goKHVubGlzdGVuKSA9PiB1bmxpc3RlbigpKTtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cImNhbnZhcy13cmFwcGVyXCI+XHJcbiAgPGNhbnZhcyBpZD1cImNhbnZhc1wiICNkcmF3aW5nQ2FudmFzPjwvY2FudmFzPlxyXG48L2Rpdj5cclxuPGRpdiBjbGFzcz1cImltYWdlLWJ1dHRvbi13cmFwcGVyXCI+XHJcbiAgPGJ1dHRvblxyXG4gICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAoY2xpY2spPVwic2F2ZSgpXCJcclxuICAgIGNsYXNzPVwiYnV0dG9uIHNhdmVcIlxyXG4gICAgW3N0eWxlLmJhY2tncm91bmQtY29sb3JdPVwic2F2ZUJ1dHRvbkNvbG9yXCJcclxuICA+XHJcbiAgICBTYXZlXHJcbiAgPC9idXR0b24+XHJcbiAgPGJ1dHRvblxyXG4gICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAoY2xpY2spPVwiY2xlYXIoKVwiXHJcbiAgICBjbGFzcz1cImJ1dHRvbiB1bmRvXCJcclxuICAgIFtzdHlsZS5iYWNrZ3JvdW5kLWNvbG9yXT1cInVuZG9CdXR0b25Db2xvclwiXHJcbiAgPlxyXG4gICAgVW5kb1xyXG4gIDwvYnV0dG9uPlxyXG48L2Rpdj5cclxuIl19
@@ -2,7 +2,8 @@ import * as i0 from '@angular/core';
2
2
  import { EventEmitter, Component, Input, Output, ViewChild } from '@angular/core';
3
3
 
4
4
  class EasyImageDrawing {
5
- constructor() {
5
+ constructor(renderer) {
6
+ this.renderer = renderer;
6
7
  this.width = 500;
7
8
  this.height = 500;
8
9
  this.lineWidth = 7;
@@ -13,21 +14,18 @@ class EasyImageDrawing {
13
14
  this.savedImage = new EventEmitter();
14
15
  this.previousPosition = { x: 0, y: 0 };
15
16
  this.activePath = false;
16
- this._mousedown = null;
17
- this._mousemove = null;
18
- this._mouseup = null;
19
- this._touchstart = null;
20
- this._touchmove = null;
21
- this._touchend = null;
22
- }
23
- ngOnChanges() {
24
- this._setCanvas();
17
+ this.eventListeners = [];
25
18
  }
26
19
  ngAfterViewInit() {
27
20
  this._setCanvas();
28
21
  this._setMouseEvents();
29
22
  this._setMouseEventsMobile();
30
23
  }
24
+ ngOnChanges(changes) {
25
+ if (changes["src"] && !changes["src"].firstChange) {
26
+ this.clear();
27
+ }
28
+ }
31
29
  save() {
32
30
  const dataUrl = this.canvas.nativeElement.toDataURL("image/png");
33
31
  const blob = this._dataURItoBlob(dataUrl);
@@ -72,7 +70,12 @@ class EasyImageDrawing {
72
70
  return;
73
71
  this.canvas.nativeElement.width = this.width;
74
72
  this.canvas.nativeElement.height = this.height;
75
- this.context = this.canvas.nativeElement.getContext("2d");
73
+ const context = this.canvas.nativeElement.getContext("2d");
74
+ if (!context) {
75
+ console.error("Failed to get 2D context");
76
+ return;
77
+ }
78
+ this.context = context;
76
79
  this.context.lineWidth = this.lineWidth;
77
80
  this.context.strokeStyle = this.lineColor;
78
81
  this.context.lineCap = "round";
@@ -84,59 +87,53 @@ class EasyImageDrawing {
84
87
  };
85
88
  }
86
89
  _setMouseEvents() {
87
- this._mousedown = window.addEventListener("mousedown", (event) => {
88
- this.activePath = true;
89
- this.context.beginPath();
90
- this.previousPosition = this.getPosition(event.clientX, event.clientY);
91
- });
92
- this._mousemove = window.addEventListener("mousemove", (event) => {
93
- if (this.activePath) {
94
- this._drawLine(event);
95
- }
96
- });
97
- this._mouseup = window.addEventListener("mouseup", () => {
98
- if (this.activePath) {
99
- this.context.closePath();
100
- this.activePath = false;
101
- }
102
- });
90
+ this.eventListeners.push(this.renderer.listen("window", "mousedown", this._onMouseDown.bind(this)), this.renderer.listen("window", "mousemove", this._onMouseMove.bind(this)), this.renderer.listen("window", "mouseup", this._onMouseUp.bind(this)));
91
+ }
92
+ _onMouseDown(event) {
93
+ this.activePath = true;
94
+ this.context.beginPath();
95
+ this.previousPosition = this.getPosition(event.clientX, event.clientY);
96
+ }
97
+ _onMouseMove(event) {
98
+ if (this.activePath) {
99
+ this._drawLine(event);
100
+ }
101
+ }
102
+ _onMouseUp() {
103
+ if (this.activePath) {
104
+ this.context.closePath();
105
+ this.activePath = false;
106
+ }
103
107
  }
104
108
  _setMouseEventsMobile() {
105
- this._touchstart = window.addEventListener("touchstart", (event) => {
106
- this.activePath = true;
107
- this.context.beginPath();
108
- this.previousPosition = this.getPosition(event.touches[0].clientX, event.touches[0].clientY);
109
- });
110
- this._touchmove = window.addEventListener("touchmove", (event) => {
111
- if (this.activePath) {
112
- this._drawLine(event.touches[0]);
113
- }
114
- });
115
- this._touchend = window.addEventListener("touchend", () => {
116
- if (this.activePath) {
117
- this.context.closePath();
118
- this.activePath = false;
119
- }
120
- });
121
- }
122
- _removeEventListeners() {
123
- window.removeEventListener("mousedown", this._mousedown);
124
- window.removeEventListener("mousemove", this._mousemove);
125
- window.removeEventListener("mouseup", this._mouseup);
126
- window.removeEventListener("touchstart", this._touchstart);
127
- window.removeEventListener("touchmove", this._touchmove);
128
- window.removeEventListener("touchend", this._touchend);
109
+ this.eventListeners.push(this.renderer.listen("window", "touchstart", this._onTouchStart.bind(this)), this.renderer.listen("window", "touchmove", this._onTouchMove.bind(this)), this.renderer.listen("window", "touchend", this._onTouchEnd.bind(this)));
110
+ }
111
+ _onTouchStart(event) {
112
+ this.activePath = true;
113
+ this.context.beginPath();
114
+ this.previousPosition = this.getPosition(event.touches[0].clientX, event.touches[0].clientY);
115
+ }
116
+ _onTouchMove(event) {
117
+ if (this.activePath) {
118
+ this._drawLine(event.touches[0]);
119
+ }
120
+ }
121
+ _onTouchEnd() {
122
+ if (this.activePath) {
123
+ this.context.closePath();
124
+ this.activePath = false;
125
+ }
129
126
  }
130
127
  ngOnDestroy() {
131
- this._removeEventListeners();
128
+ this.eventListeners.forEach((unlisten) => unlisten());
132
129
  }
133
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
130
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
134
131
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.3", type: EasyImageDrawing, isStandalone: true, selector: "easy-image-drawing", inputs: { width: "width", height: "height", lineWidth: "lineWidth", lineColor: "lineColor", src: "src", saveButtonColor: "saveButtonColor", undoButtonColor: "undoButtonColor" }, outputs: { savedImage: "savedImage" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["drawingCanvas"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}\n"] }); }
135
132
  }
136
133
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImport: i0, type: EasyImageDrawing, decorators: [{
137
134
  type: Component,
138
135
  args: [{ selector: "easy-image-drawing", standalone: true, imports: [], template: "<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n", styles: ["@media only screen and (max-width: 900px){:host{display:flex;flex-direction:column;height:100%;width:100%}}.image-button-wrapper{display:flex;justify-content:center;margin:0 10px 10px 0}#canvas{border:1px solid #ccc;cursor:crosshair;max-width:100%;max-height:100%}.canvas-wrapper{display:flex;align-items:center;justify-content:center}.button-wrapper{display:flex;justify-content:center;margin-top:10px}button{margin:1rem;border:none;border-radius:5px;color:#fff;padding:.5rem 1rem;text-align:center;text-decoration:none;display:inline-block;font-size:16px;cursor:pointer}\n"] }]
139
- }], propDecorators: { width: [{
136
+ }], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { width: [{
140
137
  type: Input
141
138
  }], height: [{
142
139
  type: Input
@@ -1 +1 @@
1
- {"version":3,"file":"ngx-easy-image-drawing.mjs","sources":["../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.ts","../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.html","../../../projects/ngx-easy-image-drawing/src/public-api.ts","../../../projects/ngx-easy-image-drawing/src/ngx-easy-image-drawing.ts"],"sourcesContent":["import {\r\n Component,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n Input,\r\n Output,\r\n EventEmitter,\r\n OnDestroy,\r\n OnChanges,\r\n} from \"@angular/core\";\r\n\r\n@Component({\r\n selector: \"easy-image-drawing\",\r\n standalone: true,\r\n imports: [],\r\n templateUrl: \"./easy-image-drawing.component.html\",\r\n styleUrls: [\"./easy-image-drawing.component.scss\"],\r\n})\r\nexport class EasyImageDrawing implements OnChanges, AfterViewInit, OnDestroy {\r\n @Input() width: number = 500;\r\n @Input() height: number = 500;\r\n @Input() lineWidth = 7;\r\n @Input() lineColor = \"#000000\";\r\n @Input() src = \"\";\r\n @Input() saveButtonColor = \"#4caf50\";\r\n @Input() undoButtonColor = \"#f44336\";\r\n @Output() savedImage = new EventEmitter<File>();\r\n\r\n // its important myCanvas matches the variable name in the template\r\n @ViewChild(\"drawingCanvas\") canvas!: ElementRef<HTMLCanvasElement>;\r\n\r\n context!: CanvasRenderingContext2D;\r\n private previousPosition: { x: number; y: number } = { x: 0, y: 0 };\r\n private activePath = false;\r\n\r\n private _mousedown: any = null;\r\n private _mousemove: any = null;\r\n private _mouseup: any = null;\r\n\r\n private _touchstart: any = null;\r\n private _touchmove: any = null;\r\n private _touchend: any = null;\r\n\r\n ngOnChanges(): void {\r\n this._setCanvas();\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n this._setCanvas();\r\n this._setMouseEvents();\r\n this._setMouseEventsMobile();\r\n }\r\n\r\n public save(): void {\r\n const dataUrl = this.canvas.nativeElement.toDataURL(\"image/png\");\r\n const blob = this._dataURItoBlob(dataUrl);\r\n this.savedImage.next(new File([blob], \"image.png\"));\r\n }\r\n\r\n public clear(): void {\r\n this.context.clearRect(0, 0, this.width, this.height);\r\n const image = new Image();\r\n image.src = this.src;\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width, this.height);\r\n };\r\n }\r\n\r\n private _dataURItoBlob(dataUrl: string) {\r\n const byteString = atob(dataUrl.split(\",\")[1]);\r\n const mimeString = dataUrl.split(\",\")[0].split(\":\")[1].split(\";\")[0];\r\n const ab = new ArrayBuffer(byteString.length);\r\n const dw = new DataView(ab);\r\n for (let i = 0; i < byteString.length; i++) {\r\n dw.setUint8(i, byteString.charCodeAt(i));\r\n }\r\n return new Blob([ab], { type: mimeString });\r\n }\r\n\r\n private _drawLine(event: any): void {\r\n const currentPosition = this.getPosition(event.clientX, event.clientY);\r\n this.context.moveTo(this.previousPosition.x, this.previousPosition.y);\r\n this.context.lineTo(currentPosition.x, currentPosition.y);\r\n this.previousPosition = currentPosition;\r\n this.context.stroke();\r\n }\r\n\r\n private getPosition(\r\n clientX: number,\r\n clientY: number\r\n ): { x: number; y: number } {\r\n const rect = this.canvas.nativeElement.getBoundingClientRect();\r\n const scaleX = this.canvas.nativeElement.width / rect.width;\r\n const scaleY = this.canvas.nativeElement.height / rect.height;\r\n return {\r\n x: (clientX - rect.left) * scaleX,\r\n y: (clientY - rect.top) * scaleY,\r\n };\r\n }\r\n\r\n private _setCanvas(): void {\r\n if (!this.canvas) return;\r\n\r\n this.canvas.nativeElement.width = this.width;\r\n this.canvas.nativeElement.height = this.height;\r\n\r\n this.context = this.canvas.nativeElement.getContext(\"2d\")!;\r\n this.context.lineWidth = this.lineWidth;\r\n this.context.strokeStyle = this.lineColor;\r\n this.context.lineCap = \"round\";\r\n\r\n // set src to image\r\n const image = new Image();\r\n image.src = this.src;\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width, this.height);\r\n };\r\n }\r\n\r\n private _setMouseEvents(): void {\r\n this._mousedown = window.addEventListener(\r\n \"mousedown\",\r\n (event: MouseEvent) => {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(event.clientX, event.clientY);\r\n }\r\n );\r\n\r\n this._mousemove = window.addEventListener(\"mousemove\", (event) => {\r\n if (this.activePath) {\r\n this._drawLine(event);\r\n }\r\n });\r\n\r\n this._mouseup = window.addEventListener(\"mouseup\", () => {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n });\r\n }\r\n\r\n private _setMouseEventsMobile(): void {\r\n this._touchstart = window.addEventListener(\r\n \"touchstart\",\r\n (event: TouchEvent) => {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(\r\n event.touches[0].clientX,\r\n event.touches[0].clientY\r\n );\r\n }\r\n );\r\n\r\n this._touchmove = window.addEventListener(\"touchmove\", (event) => {\r\n if (this.activePath) {\r\n this._drawLine(event.touches[0]);\r\n }\r\n });\r\n\r\n this._touchend = window.addEventListener(\"touchend\", () => {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n });\r\n }\r\n\r\n private _removeEventListeners(): void {\r\n window.removeEventListener(\"mousedown\", this._mousedown);\r\n window.removeEventListener(\"mousemove\", this._mousemove);\r\n window.removeEventListener(\"mouseup\", this._mouseup);\r\n window.removeEventListener(\"touchstart\", this._touchstart);\r\n window.removeEventListener(\"touchmove\", this._touchmove);\r\n window.removeEventListener(\"touchend\", this._touchend);\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this._removeEventListeners();\r\n }\r\n}\r\n","<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n","/*\r\n * Public API Surface of ngx-easy-image-drawing\r\n */\r\n\r\nexport * from \"./lib/easy-image-drawing.component\";\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngx-easy-image-drawing.mjs","sources":["../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.ts","../../../projects/ngx-easy-image-drawing/src/lib/easy-image-drawing.component.html","../../../projects/ngx-easy-image-drawing/src/public-api.ts","../../../projects/ngx-easy-image-drawing/src/ngx-easy-image-drawing.ts"],"sourcesContent":["import {\r\n Component,\r\n ViewChild,\r\n ElementRef,\r\n AfterViewInit,\r\n Input,\r\n Output,\r\n EventEmitter,\r\n OnDestroy,\r\n OnChanges,\r\n Renderer2,\r\n SimpleChanges,\r\n} from \"@angular/core\";\r\n\r\n@Component({\r\n selector: \"easy-image-drawing\",\r\n standalone: true,\r\n imports: [],\r\n templateUrl: \"./easy-image-drawing.component.html\",\r\n styleUrls: [\"./easy-image-drawing.component.scss\"],\r\n})\r\nexport class EasyImageDrawing implements OnChanges, AfterViewInit, OnDestroy {\r\n @Input() width: number = 500;\r\n @Input() height: number = 500;\r\n @Input() lineWidth: number = 7;\r\n @Input() lineColor = \"#000000\";\r\n @Input() src = \"\";\r\n @Input() saveButtonColor = \"#4caf50\";\r\n @Input() undoButtonColor = \"#f44336\";\r\n @Output() savedImage = new EventEmitter<File>();\r\n\r\n // its important myCanvas matches the variable name in the template\r\n @ViewChild(\"drawingCanvas\") canvas!: ElementRef<HTMLCanvasElement>;\r\n\r\n context!: CanvasRenderingContext2D;\r\n private previousPosition: { x: number; y: number } = { x: 0, y: 0 };\r\n private activePath = false;\r\n private eventListeners: (() => void)[] = [];\r\n\r\n constructor(private renderer: Renderer2) {}\r\n\r\n ngAfterViewInit(): void {\r\n this._setCanvas();\r\n this._setMouseEvents();\r\n this._setMouseEventsMobile();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes[\"src\"] && !changes[\"src\"].firstChange) {\r\n this.clear();\r\n }\r\n }\r\n public save(): void {\r\n const dataUrl = this.canvas.nativeElement.toDataURL(\"image/png\");\r\n const blob = this._dataURItoBlob(dataUrl);\r\n this.savedImage.next(new File([blob], \"image.png\"));\r\n }\r\n\r\n public clear(): void {\r\n this.context.clearRect(0, 0, this.width, this.height);\r\n const image = new Image();\r\n image.src = this.src;\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width, this.height);\r\n };\r\n }\r\n\r\n private _dataURItoBlob(dataUrl: string) {\r\n const byteString = atob(dataUrl.split(\",\")[1]);\r\n const mimeString = dataUrl.split(\",\")[0].split(\":\")[1].split(\";\")[0];\r\n const ab = new ArrayBuffer(byteString.length);\r\n const dw = new DataView(ab);\r\n for (let i = 0; i < byteString.length; i++) {\r\n dw.setUint8(i, byteString.charCodeAt(i));\r\n }\r\n return new Blob([ab], { type: mimeString });\r\n }\r\n\r\n private _drawLine(event: MouseEvent | Touch): void {\r\n const currentPosition = this.getPosition(event.clientX, event.clientY);\r\n this.context.moveTo(this.previousPosition.x, this.previousPosition.y);\r\n this.context.lineTo(currentPosition.x, currentPosition.y);\r\n this.previousPosition = currentPosition;\r\n this.context.stroke();\r\n }\r\n\r\n private getPosition(\r\n clientX: number,\r\n clientY: number\r\n ): { x: number; y: number } {\r\n const rect = this.canvas.nativeElement.getBoundingClientRect();\r\n const scaleX = this.canvas.nativeElement.width / rect.width;\r\n const scaleY = this.canvas.nativeElement.height / rect.height;\r\n return {\r\n x: (clientX - rect.left) * scaleX,\r\n y: (clientY - rect.top) * scaleY,\r\n };\r\n }\r\n\r\n private _setCanvas(): void {\r\n if (!this.canvas) return;\r\n\r\n this.canvas.nativeElement.width = this.width;\r\n this.canvas.nativeElement.height = this.height;\r\n\r\n const context = this.canvas.nativeElement.getContext(\"2d\");\r\n if (!context) {\r\n console.error(\"Failed to get 2D context\");\r\n return;\r\n }\r\n this.context = context;\r\n this.context.lineWidth = this.lineWidth;\r\n this.context.strokeStyle = this.lineColor;\r\n this.context.lineCap = \"round\";\r\n\r\n // set src to image\r\n const image = new Image();\r\n image.src = this.src;\r\n image.onload = () => {\r\n this.context.drawImage(image, 0, 0, this.width, this.height);\r\n };\r\n }\r\n\r\n private _setMouseEvents(): void {\r\n this.eventListeners.push(\r\n this.renderer.listen(\"window\", \"mousedown\", this._onMouseDown.bind(this)),\r\n this.renderer.listen(\"window\", \"mousemove\", this._onMouseMove.bind(this)),\r\n this.renderer.listen(\"window\", \"mouseup\", this._onMouseUp.bind(this))\r\n );\r\n }\r\n\r\n private _onMouseDown(event: MouseEvent): void {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(event.clientX, event.clientY);\r\n }\r\n\r\n private _onMouseMove(event: MouseEvent): void {\r\n if (this.activePath) {\r\n this._drawLine(event);\r\n }\r\n }\r\n\r\n private _onMouseUp(): void {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n }\r\n\r\n private _setMouseEventsMobile(): void {\r\n this.eventListeners.push(\r\n this.renderer.listen(\r\n \"window\",\r\n \"touchstart\",\r\n this._onTouchStart.bind(this)\r\n ),\r\n this.renderer.listen(\"window\", \"touchmove\", this._onTouchMove.bind(this)),\r\n this.renderer.listen(\"window\", \"touchend\", this._onTouchEnd.bind(this))\r\n );\r\n }\r\n\r\n private _onTouchStart(event: TouchEvent): void {\r\n this.activePath = true;\r\n this.context.beginPath();\r\n this.previousPosition = this.getPosition(\r\n event.touches[0].clientX,\r\n event.touches[0].clientY\r\n );\r\n }\r\n\r\n private _onTouchMove(event: TouchEvent): void {\r\n if (this.activePath) {\r\n this._drawLine(event.touches[0]);\r\n }\r\n }\r\n\r\n private _onTouchEnd(): void {\r\n if (this.activePath) {\r\n this.context.closePath();\r\n this.activePath = false;\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.eventListeners.forEach((unlisten) => unlisten());\r\n }\r\n}\r\n","<div class=\"canvas-wrapper\">\r\n <canvas id=\"canvas\" #drawingCanvas></canvas>\r\n</div>\r\n<div class=\"image-button-wrapper\">\r\n <button\r\n type=\"button\"\r\n (click)=\"save()\"\r\n class=\"button save\"\r\n [style.background-color]=\"saveButtonColor\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"clear()\"\r\n class=\"button undo\"\r\n [style.background-color]=\"undoButtonColor\"\r\n >\r\n Undo\r\n </button>\r\n</div>\r\n","/*\r\n * Public API Surface of ngx-easy-image-drawing\r\n */\r\n\r\nexport * from \"./lib/easy-image-drawing.component\";\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import { ElementRef, AfterViewInit, EventEmitter, OnDestroy, OnChanges } from "@angular/core";
1
+ import { ElementRef, AfterViewInit, EventEmitter, OnDestroy, OnChanges, Renderer2, SimpleChanges } from "@angular/core";
2
2
  import * as i0 from "@angular/core";
3
3
  export declare class EasyImageDrawing implements OnChanges, AfterViewInit, OnDestroy {
4
+ private renderer;
4
5
  width: number;
5
6
  height: number;
6
7
  lineWidth: number;
@@ -13,14 +14,10 @@ export declare class EasyImageDrawing implements OnChanges, AfterViewInit, OnDes
13
14
  context: CanvasRenderingContext2D;
14
15
  private previousPosition;
15
16
  private activePath;
16
- private _mousedown;
17
- private _mousemove;
18
- private _mouseup;
19
- private _touchstart;
20
- private _touchmove;
21
- private _touchend;
22
- ngOnChanges(): void;
17
+ private eventListeners;
18
+ constructor(renderer: Renderer2);
23
19
  ngAfterViewInit(): void;
20
+ ngOnChanges(changes: SimpleChanges): void;
24
21
  save(): void;
25
22
  clear(): void;
26
23
  private _dataURItoBlob;
@@ -28,8 +25,13 @@ export declare class EasyImageDrawing implements OnChanges, AfterViewInit, OnDes
28
25
  private getPosition;
29
26
  private _setCanvas;
30
27
  private _setMouseEvents;
28
+ private _onMouseDown;
29
+ private _onMouseMove;
30
+ private _onMouseUp;
31
31
  private _setMouseEventsMobile;
32
- private _removeEventListeners;
32
+ private _onTouchStart;
33
+ private _onTouchMove;
34
+ private _onTouchEnd;
33
35
  ngOnDestroy(): void;
34
36
  static ɵfac: i0.ɵɵFactoryDeclaration<EasyImageDrawing, never>;
35
37
  static ɵcmp: i0.ɵɵComponentDeclaration<EasyImageDrawing, "easy-image-drawing", never, { "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "lineWidth": { "alias": "lineWidth"; "required": false; }; "lineColor": { "alias": "lineColor"; "required": false; }; "src": { "alias": "src"; "required": false; }; "saveButtonColor": { "alias": "saveButtonColor"; "required": false; }; "undoButtonColor": { "alias": "undoButtonColor"; "required": false; }; }, { "savedImage": "savedImage"; }, never, never, true, never>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-easy-image-drawing",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "author": "Alex Voronin <alex.varonin@gmail.com>",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {