UNPKG

@inweb/markup

Version:
2,383 lines 89.4 kB
import Konva from "konva";

class WorldTransform {
    screenToWorld(position) {
        return {
            x: position.x,
            y: position.y,
            z: 0
        };
    }
    worldToScreen(position) {
        return {
            x: position.x,
            y: position.y
        };
    }
    getScale() {
        return {
            x: 1,
            y: 1,
            z: 1
        };
    }
}

class MarkupColor {
    constructor(r, g, b) {
        this.setColor(r, g, b);
    }
    asHex() {
        return "#" + this.HEX;
    }
    asRGB() {
        return {
            r: this.R,
            g: this.G,
            b: this.B
        };
    }
    setColor(r, g, b) {
        this.R = r;
        this.G = g;
        this.B = b;
        this.HEX = this.rgbToHex(r, g, b);
    }
    rgbToHex(r, g, b) {
        const valueToHex = c => {
            const hex = c.toString(16);
            return hex === "0" ? "00" : hex;
        };
        return valueToHex(r) + valueToHex(g) + valueToHex(b);
    }
}

const LineTypeSpecs = new Map([ [ "solid", [] ], [ "dot", [ 30, 30, .001, 30 ] ], [ "dash", [ 30, 30 ] ] ]);

class KonvaLine {
    constructor(params, ref = null, worldTransformer = new WorldTransform) {
        var _a, _b;
        this._worldTransformer = worldTransformer;
        if (ref) {
            this._ref = ref;
            let wcsPoints = this._ref.getAttr("wcsPoints");
            if (!wcsPoints) {
                wcsPoints = [];
                let points = this._ref.points();
                let wcsPoint;
                for (let i = 0; i < points.length; i += 2) {
                    wcsPoint = this._worldTransformer.screenToWorld({
                        x: points[i],
                        y: points[i + 1]
                    });
                    wcsPoints.push({
                        x: wcsPoint.x,
                        y: wcsPoint.y,
                        z: wcsPoint.z
                    });
                }
                this._ref.setAttr("wcsPoints", wcsPoints);
            }
            return;
        }
        if (!params) params = {};
        if (!params.points) params.points = [ {
            x: 0,
            y: 0
        }, {
            x: 100,
            y: 100
        } ];
        const konvaPoints = [];
        const wcsPoints = [];
        params.points.forEach((point => {
            konvaPoints.push(point.x, point.y);
            let wcsPoint = this._worldTransformer.screenToWorld({
                x: point.x,
                y: point.y
            });
            wcsPoints.push({
                x: wcsPoint.x,
                y: wcsPoint.y,
                z: wcsPoint.z
            });
        }));
        this._ref = new Konva.Line({
            stroke: (_a = params.color) !== null && _a !== undefined ? _a : "#ff0000",
            strokeWidth: (_b = params.width) !== null && _b !== undefined ? _b : 4,
            globalCompositeOperation: "source-over",
            lineCap: "round",
            lineJoin: "round",
            points: konvaPoints,
            draggable: true,
            strokeScaleEnabled: false,
            dash: LineTypeSpecs.get(params.type) || []
        });
        this._ref.setAttr("wcsPoints", wcsPoints);
        this._ref.on("transform", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
        }));
        this._ref.on("transformend", (e => {
            const absoluteTransform = this._ref.getAbsoluteTransform();
            let wcsPoints = [];
            let points = this._ref.points();
            let wcsPoint;
            for (let i = 0; i < points.length; i += 2) {
                const position = absoluteTransform.point({
                    x: points[i],
                    y: points[i + 1]
                });
                wcsPoint = this._worldTransformer.screenToWorld({
                    x: position.x,
                    y: position.y
                });
                wcsPoints.push({
                    x: wcsPoint.x,
                    y: wcsPoint.y,
                    z: wcsPoint.z
                });
            }
            this._ref.setAttr("wcsPoints", wcsPoints);
        }));
        this._ref.on("dragend", (e => {
            const absoluteTransform = this._ref.getAbsoluteTransform();
            let wcsPoints = [];
            let points = this._ref.points();
            let wcsPoint;
            for (let i = 0; i < points.length; i += 2) {
                const position = absoluteTransform.point({
                    x: points[i],
                    y: points[i + 1]
                });
                wcsPoint = this._worldTransformer.screenToWorld({
                    x: position.x,
                    y: position.y
                });
                wcsPoints.push({
                    x: wcsPoint.x,
                    y: wcsPoint.y,
                    z: wcsPoint.z
                });
            }
            this._ref.setAttr("wcsPoints", wcsPoints);
        }));
        this._ref.id(this._ref._id.toString());
    }
    ref() {
        return this._ref;
    }
    id() {
        return this._ref.id();
    }
    enableMouseEditing(value) {
        this._ref.draggable(value);
    }
    type() {
        return "Line";
    }
    getColor() {
        return this._ref.stroke();
    }
    setColor(hex) {
        this._ref.stroke(hex);
    }
    getRotation() {
        return this._ref.rotation();
    }
    setRotation(degrees) {
        this._ref.rotation(degrees);
    }
    getZIndex() {
        return this._ref.zIndex();
    }
    setZIndex(zIndex) {
        this._ref.zIndex(zIndex);
    }
    delete() {
        this._ref.destroy();
        this._ref = null;
    }
    getPoints() {
        return this._ref.points();
    }
    setLineWidth(size) {
        this._ref.strokeWidth(size);
    }
    getLineWidth() {
        return this._ref.strokeWidth();
    }
    getLineType() {
        const typeSpecs = this._ref.dash() || [];
        let type;
        switch (typeSpecs) {
          case LineTypeSpecs.get("dot"):
            type = "dot";
            break;

          case LineTypeSpecs.get("dash"):
            type = "dash";
            break;

          default:
            type = "solid";
            break;
        }
        return type;
    }
    setLineType(type) {
        const specs = LineTypeSpecs.get(type);
        if (specs) this._ref.dash(specs);
    }
    addPoints(points) {
        let newPoints = this._ref.points();
        let wcsPoints = this._ref.getAttr("wcsPoints");
        points.forEach((point => {
            newPoints = newPoints.concat([ point.x, point.y ]);
            let wcsPoint = this._worldTransformer.screenToWorld(point);
            wcsPoints.push(wcsPoint);
        }));
        this._ref.points(newPoints);
    }
    updateScreenCoordinates() {
        let wcsPoints = this._ref.getAttr("wcsPoints");
        let points = [];
        let invert = this._ref.getAbsoluteTransform().copy();
        invert = invert.invert();
        wcsPoints.forEach((point => {
            let screenPoint = this._worldTransformer.worldToScreen(point);
            screenPoint = invert.point({
                x: screenPoint.x,
                y: screenPoint.y
            });
            points.push(screenPoint.x);
            points.push(screenPoint.y);
        }));
        this._ref.points([]);
        this._ref.points(points);
        this._ref.clearCache();
    }
}

class KonvaText {
    constructor(params, ref = null, worldTransformer = new WorldTransform) {
        var _a, _b, _c;
        this.TEXT_FONT_FAMILY = "Calibri";
        this._worldTransformer = worldTransformer;
        if (ref) {
            this._ref = ref;
            const wcsStart = this._ref.getAttr("wcsStart");
            if (!wcsStart) {
                this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
                    x: ref.x(),
                    y: ref.y()
                }));
            }
            return;
        }
        if (!params) params = {};
        if (!params.position) params.position = {
            x: 0,
            y: 0
        };
        if (!params.text) params.text = "default";
        this._ref = new Konva.Text({
            x: params.position.x,
            y: params.position.y,
            text: params.text,
            fontSize: (_a = params.fontSize) !== null && _a !== undefined ? _a : 34,
            fontFamily: this.TEXT_FONT_FAMILY,
            fill: (_b = params.color) !== null && _b !== undefined ? _b : "#ff0000",
            align: "left",
            draggable: true,
            rotation: (_c = params.rotation) !== null && _c !== undefined ? _c : 0
        });
        this._ref.width(this._ref.getTextWidth());
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: params.position.x,
            y: params.position.y
        }));
        this._ref.on("transform", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
            const scaleByX = Math.abs(attrs.scaleX - 1) > 1e-5;
            const scaleByY = Math.abs(attrs.scaleY - 1) > 1e-5;
            let newWidth = this._ref.width();
            if (scaleByX) newWidth *= attrs.scaleX;
            let newHeight = this._ref.height();
            if (scaleByY) newHeight *= attrs.scaleY;
            const minWidth = 50;
            if (newWidth < minWidth) newWidth = minWidth;
            if (newHeight < Math.round(this.getFontSize())) newHeight = Math.round(this.getFontSize());
            if (scaleByX) {
                this._ref.width(newWidth);
            }
            if (scaleByY) {
                this._ref.height(newHeight);
            }
            this._ref.scale({
                x: 1,
                y: 1
            });
        }));
        this._ref.on("transformend", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
        }));
        this._ref.on("dragend", (e => {
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
        }));
        this._ref.id(this._ref._id.toString());
    }
    ref() {
        return this._ref;
    }
    id() {
        return this._ref.id();
    }
    enableMouseEditing(value) {
        this._ref.draggable(value);
    }
    type() {
        return "Text";
    }
    getColor() {
        return this._ref.fill();
    }
    setColor(hex) {
        this._ref.fill(hex);
    }
    getRotation() {
        return this._ref.rotation();
    }
    setRotation(degrees) {
        this._ref.rotation(degrees);
    }
    getZIndex() {
        return this._ref.zIndex();
    }
    setZIndex(zIndex) {
        this._ref.zIndex(zIndex);
    }
    delete() {
        this._ref.destroy();
        this._ref = null;
    }
    getText() {
        return this._ref.text();
    }
    setText(text) {
        this._ref.text(text);
    }
    getPosition() {
        return this._ref.getPosition();
    }
    setPosition(x, y) {
        this._ref.setPosition({
            x: x,
            y: y
        });
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: x,
            y: y
        }));
    }
    getFontSize() {
        return this._ref.fontSize();
    }
    setFontSize(size) {
        this._ref.fontSize(size);
    }
    updateScreenCoordinates() {
        let screenPositionStart = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
        let invert = this._ref.getStage().getAbsoluteTransform().copy();
        invert = invert.invert();
        const positionStart = invert.point(screenPositionStart);
        this._ref.position({
            x: positionStart.x,
            y: positionStart.y
        });
    }
}

class KonvaRectangle {
    constructor(params, ref = null, worldTransformer = new WorldTransform) {
        var _a, _b, _c, _d;
        this._worldTransformer = worldTransformer;
        if (ref) {
            this._ref = ref;
            const wcsStart = this._ref.getAttr("wcsStart");
            const wcsEnd = this._ref.getAttr("wcsEnd");
            if (!wcsStart) {
                this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
                    x: ref.x(),
                    y: ref.y()
                }));
            }
            if (!wcsEnd) {
                const rightBottomPoint = {
                    x: ref.x() + ref.width(),
                    y: ref.y() + ref.height()
                };
                this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                    x: rightBottomPoint.x,
                    y: rightBottomPoint.y
                }));
            }
            return;
        }
        if (!params) params = {};
        if (!params.position) params.position = {
            x: 0,
            y: 0
        };
        if (params.position2) {
            params.width = params.position.x - params.position2.x;
            params.height = params.position.y - params.position2.y;
        } else {
            if (!params.width || !params.height) {
                params.position2 = {
                    x: 200,
                    y: 200
                };
                params.width = 200;
                params.height = 200;
            } else {
                params.position2 = {
                    x: params.position.x + params.width,
                    y: params.position.y + params.height
                };
            }
        }
        this._ref = new Konva.Rect({
            stroke: (_a = params.color) !== null && _a !== undefined ? _a : "#ff0000",
            strokeWidth: (_b = params.lineWidth) !== null && _b !== undefined ? _b : 4,
            globalCompositeOperation: "source-over",
            lineCap: "round",
            lineJoin: "round",
            x: params.position.x,
            y: params.position.y,
            width: (_c = params.width) !== null && _c !== undefined ? _c : 200,
            height: (_d = params.height) !== null && _d !== undefined ? _d : 200,
            draggable: true,
            strokeScaleEnabled: false
        });
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: params.position.x,
            y: params.position.y
        }));
        this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
            x: params.position2.x,
            y: params.position2.y
        }));
        this._ref.on("transform", (e => {
            const attrs = e.target.attrs;
            const scaleByX = Math.abs(attrs.scaleX - 1) > 1e-5;
            const scaleByY = Math.abs(attrs.scaleY - 1) > 1e-5;
            let newWidth = this._ref.width();
            if (scaleByX) newWidth *= attrs.scaleX;
            let newHeight = this._ref.height();
            if (scaleByY) newHeight *= attrs.scaleY;
            const minWidth = 50;
            const minHeight = 50;
            if (newWidth < minWidth) newWidth = minWidth;
            if (newHeight < minHeight) newHeight = minHeight;
            if (scaleByX) {
                this._ref.width(newWidth);
            }
            if (scaleByY) {
                this._ref.height(newHeight);
            }
            this._ref.scale({
                x: 1,
                y: 1
            });
        }));
        this._ref.on("transformend", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
            this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                x: position.x + this._ref.width(),
                y: position.y + this._ref.height()
            }));
        }));
        this._ref.on("dragend", (e => {
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
            this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                x: position.x + this._ref.width(),
                y: position.y + this._ref.height()
            }));
        }));
        this._ref.id(this._ref._id.toString());
    }
    getPosition() {
        return this._ref.position();
    }
    getWidth() {
        return this._ref.width();
    }
    getHeigth() {
        return this._ref.height();
    }
    setWidth(w) {
        this._ref.width(w);
        const rightLowerPoint = {
            x: this._ref.x() + w,
            y: this._ref.y() + this._ref.height()
        };
        const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
        this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
    }
    setHeight(h) {
        this._ref.height(h);
        const rightLowerPoint = {
            x: this._ref.x() + this._ref.width(),
            y: this._ref.y() + h
        };
        const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
        this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
    }
    setPosition(x, y) {
        this._ref.setPosition({
            x: x,
            y: y
        });
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: x,
            y: y
        }));
    }
    ref() {
        return this._ref;
    }
    id() {
        return this._ref.id();
    }
    enableMouseEditing(value) {
        this._ref.draggable(value);
    }
    type() {
        return "Rectangle";
    }
    getColor() {
        return this._ref.stroke();
    }
    setColor(hex) {
        this._ref.stroke(hex);
    }
    getRotation() {
        return this._ref.rotation();
    }
    setRotation(degrees) {
        this._ref.rotation(degrees);
    }
    getZIndex() {
        return this._ref.zIndex();
    }
    setZIndex(zIndex) {
        this._ref.zIndex(zIndex);
    }
    delete() {
        this._ref.destroy();
        this._ref = null;
    }
    setLineWidth(size) {
        this._ref.strokeWidth(size);
    }
    getLineWidth() {
        return this._ref.strokeWidth();
    }
    updateScreenCoordinates() {
        let screenPositionStart = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
        let screenPositionEnd = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsEnd"));
        let invert = this._ref.getStage().getAbsoluteTransform().copy();
        invert = invert.invert();
        const positionStart = invert.point(screenPositionStart);
        const positionEnd = invert.point(screenPositionEnd);
        this._ref.position({
            x: positionStart.x,
            y: positionStart.y
        });
        this._ref.width(Math.abs(positionEnd.x - positionStart.x));
        this._ref.height(Math.abs(positionEnd.y - positionStart.y));
    }
}

class KonvaEllipse {
    constructor(params, ref = null, worldTransformer = new WorldTransform) {
        var _a, _b;
        this._worldTransformer = worldTransformer;
        if (ref) {
            this._ref = ref;
            const wcsPosition = this._ref.getAttr("wcsPosition");
            const radiusX = this._ref.getAttr("wcsRadiusX");
            const radiusY = this._ref.getAttr("wcsRadiusY");
            if (!wcsPosition) {
                this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld({
                    x: ref.x(),
                    y: ref.y()
                }));
            }
            if (!radiusX) {
                this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld({
                    x: ref.x() + ref.radiusX(),
                    y: ref.y()
                }));
            }
            if (!radiusY) {
                this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld({
                    x: ref.x(),
                    y: ref.y() + ref.radiusY()
                }));
            }
            return;
        }
        if (!params) params = {};
        if (!params.position) params.position = {
            x: 0,
            y: 0
        };
        if (!params.radius) params.radius = {
            x: 25,
            y: 25
        };
        this._ref = new Konva.Ellipse({
            stroke: (_a = params.color) !== null && _a !== undefined ? _a : "#ff0000",
            strokeWidth: (_b = params.lineWidth) !== null && _b !== undefined ? _b : 4,
            globalCompositeOperation: "source-over",
            lineCap: "round",
            lineJoin: "round",
            x: params.position.x,
            y: params.position.y,
            radiusX: params.radius.x,
            radiusY: params.radius.y,
            draggable: true,
            strokeScaleEnabled: false
        });
        this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld({
            x: params.position.x,
            y: params.position.y
        }));
        this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld({
            x: this._ref.x() + params.radius.x,
            y: this._ref.y()
        }));
        this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld({
            x: this._ref.x(),
            y: this._ref.y() + params.radius.y
        }));
        this._ref.on("transform", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
            const scaleByX = Math.abs(attrs.scaleX - 1) > 1e-5;
            const scaleByY = Math.abs(attrs.scaleY - 1) > 1e-5;
            let newRadiusX = this._ref.radiusX();
            if (scaleByX) newRadiusX *= attrs.scaleX;
            let newRadiusY = this._ref.radiusY();
            if (scaleByY) newRadiusY *= attrs.scaleY;
            const minRadiusX = 25;
            const minRadiusY = 25;
            if (newRadiusX < minRadiusX) newRadiusX = minRadiusX;
            if (newRadiusY < minRadiusY) newRadiusY = minRadiusY;
            if (e.evt.ctrlKey || e.evt.shiftKey) {
                if (scaleByX) {
                    this._ref.radius({
                        x: newRadiusX,
                        y: newRadiusX
                    });
                } else {
                    this._ref.radius({
                        x: newRadiusY,
                        y: newRadiusY
                    });
                }
            } else {
                this._ref.radius({
                    x: newRadiusX,
                    y: newRadiusY
                });
            }
            this._ref.scale({
                x: 1,
                y: 1
            });
        }));
        this._ref.on("transformend", (e => {
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld(position));
            const radiusX = absoluteTransform.point({
                x: this._ref.x() + this._ref.radiusX(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld(radiusX));
            const radiusY = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y() + this._ref.radiusY()
            });
            this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld(radiusY));
        }));
        this._ref.on("dragend", (e => {
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld(position));
            const radiusX = absoluteTransform.point({
                x: this._ref.x() + this._ref.radiusX(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld(radiusX));
            const radiusY = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y() + this._ref.radiusY()
            });
            this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld(radiusY));
        }));
        this._ref.id(this._ref._id.toString());
    }
    getPosition() {
        return this._ref.position();
    }
    setPosition(x, y) {
        this._ref.setPosition({
            x: x,
            y: y
        });
        this._ref.setAttr("wcsPosition", this._worldTransformer.screenToWorld({
            x: x,
            y: y
        }));
    }
    getRadiusX() {
        return this._ref.radiusX();
    }
    setRadiusX(r) {
        this._ref.radiusX(r);
        this._ref.setAttr("wcsRadiusX", this._worldTransformer.screenToWorld({
            x: this._ref.x() + r,
            y: this._ref.y()
        }));
    }
    getRadiusY() {
        return this._ref.radiusY();
    }
    setRadiusY(r) {
        this._ref.radiusY(r);
        this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld({
            x: this._ref.x(),
            y: this._ref.y() + r
        }));
    }
    getLineWidth() {
        return this._ref.strokeWidth();
    }
    setLineWidth(size) {
        this._ref.strokeWidth(size);
    }
    ref() {
        return this._ref;
    }
    id() {
        return this._ref.id();
    }
    enableMouseEditing(value) {
        this._ref.draggable(value);
    }
    type() {
        return "Ellipse";
    }
    getColor() {
        return this._ref.stroke();
    }
    setColor(hex) {
        this._ref.stroke(hex);
    }
    getRotation() {
        return this._ref.rotation();
    }
    setRotation(degrees) {
        this._ref.rotation(degrees);
    }
    getZIndex() {
        return this._ref.zIndex();
    }
    setZIndex(zIndex) {
        this._ref.zIndex(zIndex);
    }
    delete() {
        this._ref.destroy();
        this._ref = null;
    }
    updateScreenCoordinates() {
        let screenPosition = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsPosition"));
        let radiusX = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsRadiusX"));
        let radiusY = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsRadiusY"));
        let invert = this._ref.getStage().getAbsoluteTransform().copy();
        invert = invert.invert();
        const position = invert.point({
            x: screenPosition.x,
            y: screenPosition.y
        });
        this._ref.position({
            x: position.x,
            y: position.y
        });
        this._ref.radius({
            x: Math.abs(invert.point(radiusX).x - position.x),
            y: Math.abs(invert.point(radiusY).y - position.y)
        });
    }
}

class KonvaArrow {
    constructor(params, ref = null, worldTransformer = new WorldTransform) {
        var _a, _b;
        this._worldTransformer = worldTransformer;
        if (ref) {
            this._ref = ref;
            const wcsStart = this._ref.getAttr("wcsStart");
            const wcsEnd = this._ref.getAttr("wcsEnd");
            if (!wcsStart) this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
                x: ref.points()[0],
                y: ref.points()[1]
            }));
            if (!wcsEnd) this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                x: ref.points()[2],
                y: ref.points()[3]
            }));
            return;
        }
        if (!params) params = {};
        if (!params.start) params.start = {
            x: 0,
            y: 0
        };
        if (!params.end) params.end = {
            x: 100,
            y: 100
        };
        this._ref = new Konva.Arrow({
            stroke: (_a = params.color) !== null && _a !== undefined ? _a : "#ff0000",
            fill: (_b = params.color) !== null && _b !== undefined ? _b : "#ff0000",
            strokeWidth: 4,
            globalCompositeOperation: "source-over",
            lineCap: "round",
            lineJoin: "round",
            points: [ params.start.x, params.start.y, params.end.x, params.end.y ],
            draggable: true,
            strokeScaleEnabled: false
        });
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: params.start.x,
            y: params.start.y
        }));
        this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
            x: params.end.x,
            y: params.end.y
        }));
        this._ref.on("transformend", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
            const points = this._ref.points();
            const absoluteTransform = this._ref.getAbsoluteTransform();
            const transformStart = absoluteTransform.point({
                x: points[0],
                y: points[1]
            });
            const transformEnd = absoluteTransform.point({
                x: points[2],
                y: points[3]
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(transformStart));
            this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld(transformEnd));
        }));
        this._ref.on("dragend", (e => {
            const points = this._ref.points();
            const absoluteTransform = e.target.getAbsoluteTransform();
            const transformStart = absoluteTransform.point({
                x: points[0],
                y: points[1]
            });
            const transformEnd = absoluteTransform.point({
                x: points[2],
                y: points[3]
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(transformStart));
            this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld(transformEnd));
        }));
        this._ref.id(this._ref._id.toString());
    }
    ref() {
        return this._ref;
    }
    id() {
        return this._ref.id();
    }
    enableMouseEditing(value) {
        this._ref.draggable(value);
    }
    type() {
        return "Arrow";
    }
    getColor() {
        return this._ref.stroke();
    }
    setColor(hex) {
        this._ref.stroke(hex);
        this._ref.fill(hex);
    }
    getRotation() {
        return this._ref.rotation();
    }
    setRotation(degrees) {
        this._ref.rotation(degrees);
    }
    getZIndex() {
        return this._ref.zIndex();
    }
    setZIndex(zIndex) {
        this._ref.zIndex(zIndex);
    }
    delete() {
        this._ref.destroy();
        this._ref = null;
    }
    getPoints() {
        const points = this._ref.points();
        return [ {
            x: points[0],
            y: points[1]
        }, {
            x: points[2],
            y: points[3]
        } ];
    }
    setPoints(points) {
        if (points.length === 2) {
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
                x: points[0].x,
                y: points[0].y
            }));
            this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                x: points[1].x,
                y: points[1].y
            }));
            this._ref.points([ points[0].x, points[0].y, points[1].x, points[1].y ]);
        }
    }
    getStartPoint() {
        const points = this._ref.points();
        return {
            x: points[0],
            y: points[1]
        };
    }
    setStartPoint(x, y) {
        const points = this._ref.points();
        this._ref.points([ x, y, points[2], points[3] ]);
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: x,
            y: y
        }));
    }
    getEndPoint() {
        const points = this._ref.points();
        return {
            x: points[2],
            y: points[3]
        };
    }
    setEndPoint(x, y) {
        const points = this._ref.points();
        this._ref.points([ points[0], points[1], x, y ]);
        this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
            x: x,
            y: y
        }));
    }
    updateScreenCoordinates() {
        let screenStartPoint = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
        let screenEndPoint = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsEnd"));
        let invert = this._ref.getAbsoluteTransform().copy();
        invert = invert.invert();
        const startPoint = invert.point({
            x: screenStartPoint.x,
            y: screenStartPoint.y
        });
        const endPoint = invert.point({
            x: screenEndPoint.x,
            y: screenEndPoint.y
        });
        this._ref.points([ startPoint.x, startPoint.y, endPoint.x, endPoint.y ]);
    }
}

class KonvaImage {
    constructor(params, ref = null, worldTransformer = new WorldTransform) {
        var _a, _b;
        this._ratio = 1;
        this.EPSILON = 1e-5;
        this.BASE64_HEADER_START = "data:image/";
        this.BASE64_NOT_FOUND = "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAADsAAAA7AF5KHG9AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAmhJREFUWIXtlr9rVEEQxz+H8RQUJIdeIopYm0vkCg0GBBtbG1NF7Kxt7dR/IGIw/uhTaBNLERURg2kCEUyCYCPi70b0InjGS57FzOZN3r19d+9HJIVfWO52dma/s7Mz8xa2KAaBCWAR+AkECWOmSOIdwC1gtQOpHc+NfQ8wClQ8+1d0vcdH/lQ3bSIRGAZ2pTjAqNovANXIWlXlAXA2zvi2Ln4AjqYgtagYEutENSLvjRoOImFv5iB32Ae8UrLXwFBk3h9ndF0VJnKSO9gTu3yKu5Z1LKnS8YIcABgw5Ks692JZFXcXRJ46Aq6kikCnHNi/mQ50WwVtfaIoBzL3gRk2drSscJ2wrc4VvUoe2wn/41/iBfoVLRnBGnDSY3AAKacy8AmYR+o7K1zCl6wgrgpOAc/MuhvfgMuk+1JGHQgSBcAloKXy78AjYBppJk5/noTulseBMZ23iD/piHFkEdgTQzKk+5wHjmHC3cmBg0BD5xcSTrFXyQPgIWFtDwMvab+2N8DpbhyY1v/3E8gdDgNfVX9SCVZ0/gW4B0wB71S2BpxLcuCM/jaQSHSDEeAX4VMuAG4gTzyHbcAVXXO6GxxwIX+vvxe7JHcYQ07nHqklj96UIW/YhSWzMKcep8VVtf8B1Dw6h4DfhB+sdbgn2R+gnoEc5NR3dZ+3QJ9H74HqXLPCGlJyTfI9y3YCs0owq3OLOpKkLeBI1HhSDT/mdKIPiUCARMTlQx34TMLjtww8IczmO8AJ/N/2JNSQXAiQ671JePePge0+wzJSQq4FFzlaenIvucUAkiQLhC/mLGNZ9xgn5s63BP4CCk0QDtm4BhoAAAAASUVORK5CYII=";
        this._worldTransformer = worldTransformer;
        if (ref) {
            if (!ref.src || !ref.src.startsWith(this.BASE64_HEADER_START)) ref.src = this.BASE64_NOT_FOUND;
            if (ref.height() <= this.EPSILON) ref.height(32);
            if (ref.width() <= this.EPSILON) ref.width(32);
            this._ref = ref;
            this._canvasImage = ref.image();
            this._ratio = this._ref.height() <= this.EPSILON || this._ref.width() <= this.EPSILON ? 1 : this._ref.height() / this._ref.width();
            const wcsStart = this._ref.getAttr("wcsStart");
            if (!wcsStart) {
                this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
                    x: ref.x(),
                    y: ref.y()
                }));
            }
            return;
        }
        if (!params) params = {};
        if (!params.position) params.position = {
            x: 0,
            y: 0
        };
        if (!params.src || !params.src.startsWith(this.BASE64_HEADER_START)) params.src = this.BASE64_NOT_FOUND;
        this._canvasImage = new Image;
        this._canvasImage.onload = () => {
            this._ref.image(this._canvasImage);
            if (this._ref.height() <= this.EPSILON) this._ref.height(this._canvasImage.height);
            if (this._ref.width() <= this.EPSILON) this._ref.width(this._canvasImage.width);
            this._ratio = this._ref.height() <= this.EPSILON || this._ref.width() <= this.EPSILON ? 1 : this._ref.height() / this._ref.width();
            if ((params.width <= this.EPSILON || params.height <= this.EPSILON) && (params.maxWidth >= this.EPSILON || params.maxWidth >= this.EPSILON)) {
                const heightOutOfCanvas = params.maxHeight - this._canvasImage.height;
                const widthOutOfCanvas = params.maxWidth - this._canvasImage.width;
                if (heightOutOfCanvas <= this.EPSILON || widthOutOfCanvas <= this.EPSILON) {
                    if (widthOutOfCanvas <= this.EPSILON && widthOutOfCanvas < heightOutOfCanvas / this._ratio) {
                        this._ref.height(params.maxWidth * this._ratio);
                        this._ref.width(params.maxWidth);
                    } else {
                        this._ref.width(params.maxHeight / this._ratio);
                        this._ref.height(params.maxHeight);
                    }
                }
            }
        };
        this._canvasImage.onerror = () => {
            this._canvasImage.onerror = function() {};
            this._canvasImage.src = this.BASE64_NOT_FOUND;
        };
        this._canvasImage.src = params.src;
        this._ref = new Konva.Image({
            x: params.position.x,
            y: params.position.y,
            image: this._canvasImage,
            width: (_a = params.width) !== null && _a !== undefined ? _a : 0,
            height: (_b = params.height) !== null && _b !== undefined ? _b : 0,
            draggable: true
        });
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: params.position.x,
            y: params.position.y
        }));
        this._ref.on("transform", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
            const scaleByX = Math.abs(attrs.scaleX - 1) > 1e-5;
            const scaleByY = Math.abs(attrs.scaleY - 1) > 1e-5;
            let newWidth = this._ref.width();
            if (scaleByX) newWidth *= attrs.scaleX;
            let newHeight = this._ref.height();
            if (scaleByY) newHeight *= attrs.scaleY;
            if (e.evt.ctrlKey || e.evt.shiftKey) {
                if (scaleByX) {
                    this._ref.width(newWidth);
                    this._ref.height(newWidth * this._ratio);
                } else {
                    this._ref.width(newHeight / this._ratio);
                    this._ref.height(newHeight);
                }
            } else {
                if (scaleByX) {
                    this._ref.width(newWidth);
                }
                if (scaleByY) {
                    this._ref.height(newHeight);
                }
            }
            this._ref.scale({
                x: 1,
                y: 1
            });
        }));
        this._ref.on("transformend", (e => {
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
        }));
        this._ref.on("dragend", (e => {
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
        }));
        this._ref.id(this._ref._id.toString());
    }
    getSrc() {
        return this._canvasImage.src;
    }
    setSrc(src) {
        this._canvasImage.src = src;
    }
    getWidth() {
        return this._ref.width();
    }
    setWidth(w) {
        this._ref.width(w);
        this._ref.height(w * this._ratio);
    }
    getHeight() {
        return this._ref.height();
    }
    setHeight(h) {
        this._ref.height(h);
        this._ref.width(h / this._ratio);
    }
    ref() {
        return this._ref;
    }
    id() {
        return this._ref.id();
    }
    enableMouseEditing(value) {
        this._ref.draggable(value);
    }
    type() {
        return "Image";
    }
    getRotation() {
        return this._ref.rotation();
    }
    setRotation(degrees) {
        this._ref.rotation(degrees);
    }
    getZIndex() {
        return this._ref.zIndex();
    }
    setZIndex(zIndex) {
        this._ref.zIndex(zIndex);
    }
    delete() {
        this._ref.destroy();
        this._ref = null;
    }
    getPosition() {
        return this._ref.getPosition();
    }
    setPosition(x, y) {
        this._ref.setPosition({
            x: x,
            y: y
        });
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: x,
            y: y
        }));
    }
    updateScreenCoordinates() {
        let screenPositionStart = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
        let invert = this._ref.getStage().getAbsoluteTransform().copy();
        invert = invert.invert();
        const positionStart = invert.point(screenPositionStart);
        this._ref.position({
            x: positionStart.x,
            y: positionStart.y
        });
    }
}

class KonvaCloud {
    constructor(params, ref = null, worldTransformer = new WorldTransform) {
        var _a, _b, _c, _d;
        this._worldTransformer = worldTransformer;
        if (ref) {
            this._ref = ref;
            const wcsStart = this._ref.getAttr("wcsStart");
            const wcsEnd = this._ref.getAttr("wcsEnd");
            if (!wcsStart) {
                this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
                    x: ref.x(),
                    y: ref.y()
                }));
            }
            if (!wcsEnd) {
                const rightBottomPoint = {
                    x: ref.x() + ref.width(),
                    y: ref.y() + ref.height()
                };
                this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                    x: rightBottomPoint.x,
                    y: rightBottomPoint.y
                }));
            }
            return;
        }
        if (!params) params = {};
        if (!params.position) params.position = {
            x: 0,
            y: 0
        };
        if (params.position2) {
            params.width = params.position.x - params.position2.x;
            params.height = params.position.y - params.position2.y;
        } else {
            if (!params.width || !params.height) {
                params.position2 = {
                    x: 200,
                    y: 200
                };
                params.width = 200;
                params.height = 200;
            } else {
                params.position2 = {
                    x: params.position.x + params.width,
                    y: params.position.y + params.height
                };
            }
        }
        const ARC_RADIUS = 16;
        this._ref = new Konva.Shape({
            x: params.position.x,
            y: params.position.y,
            width: (_a = params.width) !== null && _a !== undefined ? _a : 200,
            height: (_b = params.height) !== null && _b !== undefined ? _b : 200,
            stroke: (_c = params.color) !== null && _c !== undefined ? _c : "#ff0000",
            strokeWidth: (_d = params.lineWidth) !== null && _d !== undefined ? _d : 4,
            draggable: true,
            strokeScaleEnabled: false,
            globalCompositeOperation: "source-over",
            sceneFunc: (context, shape) => {
                function calculateMidpoint(position, width, height) {
                    const midX = position.x + width / 2;
                    const midY = position.y + height / 2;
                    return {
                        x: midX,
                        y: midY
                    };
                }
                const points = [ {
                    x: 0,
                    y: 0
                }, {
                    x: 0 + this._ref.width(),
                    y: 0
                }, {
                    x: 0 + this._ref.width(),
                    y: 0 + this._ref.height()
                }, {
                    x: 0,
                    y: 0 + this._ref.height()
                }, {
                    x: 0,
                    y: 0
                } ];
                const midPoint = calculateMidpoint({
                    x: 0,
                    y: 0
                }, this._ref.width(), this._ref.height());
                const baseArcLength = 30;
                context.beginPath();
                for (let iPoint = 0; iPoint < points.length - 1; iPoint++) {
                    let approxArcLength = baseArcLength;
                    const dx = points[iPoint + 1].x - points[iPoint].x;
                    const dy = points[iPoint + 1].y - points[iPoint].y;
                    const length = Math.sqrt(dx * dx + dy * dy);
                    const arcCount = Math.floor(length / approxArcLength);
                    const lengthMod = length % approxArcLength;
                    approxArcLength = baseArcLength + arcCount / lengthMod;
                    let pX = points[iPoint].x + dx / arcCount / 2;
                    let pY = points[iPoint].y + dy / arcCount / 2;
                    const pEndX = points[iPoint + 1].x;
                    const pEndY = points[iPoint + 1].y;
                    const endAngle = Math.atan((pEndY - pY) / (pEndX - pX));
                    const startAngle = endAngle + Math.PI;
                    const counterClockwise = pX > midPoint.x && pY > midPoint.y;
                    for (let iArc = 0; iArc < arcCount; iArc++) {
                        if (counterClockwise) {
                            context.arc(pX, pY, ARC_RADIUS, endAngle, startAngle);
                        } else {
                            context.arc(pX, pY, ARC_RADIUS, startAngle, endAngle);
                        }
                        pX += dx / arcCount;
                        pY += dy / arcCount;
                    }
                }
                context.closePath();
                context.fillStrokeShape(shape);
            }
        });
        this._ref.className = "Cloud";
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: params.position.x,
            y: params.position.y
        }));
        this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
            x: params.position2.x,
            y: params.position2.y
        }));
        this._ref.on("transform", (e => {
            const attrs = e.target.attrs;
            const scaleByX = Math.abs(attrs.scaleX - 1) > 1e-5;
            const scaleByY = Math.abs(attrs.scaleY - 1) > 1e-5;
            let newWidth = this._ref.width();
            if (scaleByX) newWidth *= attrs.scaleX;
            let newHeight = this._ref.height();
            if (scaleByY) newHeight *= attrs.scaleY;
            const minWidth = 100;
            const minHeight = 100;
            if (newWidth < minWidth) newWidth = minWidth;
            if (newHeight < minHeight) newHeight = minHeight;
            if (scaleByX) {
                this._ref.width(newWidth);
            }
            if (scaleByY) {
                this._ref.height(newHeight);
            }
            this._ref.scale({
                x: 1,
                y: 1
            });
        }));
        this._ref.on("transformend", (e => {
            const attrs = e.target.attrs;
            if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
            this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                x: position.x + this._ref.width(),
                y: position.y + this._ref.height()
            }));
        }));
        this._ref.on("dragend", (e => {
            const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
            const position = absoluteTransform.point({
                x: this._ref.x(),
                y: this._ref.y()
            });
            this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
            this._ref.setAttr("wcsEnd", this._worldTransformer.screenToWorld({
                x: position.x + this._ref.width(),
                y: position.y + this._ref.height()
            }));
        }));
        this._ref.getSelfRect = () => ({
            x: 0 - ARC_RADIUS,
            y: 0 - ARC_RADIUS,
            width: this._ref.width() + 2 * ARC_RADIUS,
            height: this._ref.height() + 2 * ARC_RADIUS
        });
        this._ref.id(this._ref._id.toString());
    }
    ref() {
        return this._ref;
    }
    id() {
        return this._ref.id();
    }
    enableMouseEditing(value) {
        this._ref.draggable(value);
    }
    type() {
        return "Cloud";
    }
    getColor() {
        return this._ref.stroke();
    }
    setColor(hex) {
        this._ref.stroke(hex);
    }
    getRotation() {
        return this._ref.rotation();
    }
    setRotation(degrees) {
        this._ref.rotation(degrees);
    }
    getZIndex() {
        return this._ref.zIndex();
    }
    setZIndex(zIndex) {
        this._ref.zIndex(zIndex);
    }
    delete() {
        this._ref.destroy();
        this._ref = null;
    }
    getPosition() {
        return this._ref.position();
    }
    setPosition(x, y) {
        this._ref.position({
            x: x,
            y: y
        });
        this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld({
            x: x,
            y: y
        }));
    }
    getWidth() {
        return this._ref.width();
    }
    setWidth(w) {
        this._ref.width(w);
        const rightLowerPoint = {
            x: this._ref.x() + w,
            y: this._ref.y() + this._ref.height()
        };
        const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
        this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
    }
    getHeigth() {
        return this._ref.height();
    }
    setHeight(h) {
        this._ref.height(h);
        const rightLowerPoint = {
            x: this._ref.x() + this._ref.width(),
            y: this._ref.y() + h
        };
        const wcsRightLowerPoint = this._worldTransformer.screenToWorld(rightLowerPoint);
        this._ref.setAttr("wcsEnd", wcsRightLowerPoint);
    }
    getLineWidth() {
        return this._ref.strokeWidth();
    }
    setLineWidth(size) {
        this._ref.strokeWidth(size);
    }
    updateScreenCoordinates() {
        let screenPositionStart = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsStart"));
        let screenPositionEnd = this._worldTransformer.worldToScreen(this._ref.getAttr("wcsEnd"));
        let invert = this._ref.getStage().getAbsoluteTransform().copy();
        invert = invert.invert();
        const positionStart = invert.point(screenPositionStart);
        const positionEnd = invert.point(screenPositionEnd);
        this._ref.position({
            x: positionStart.x,
            y: positionStart.y
        });
        this._ref.width(Math.abs(positionEnd.x - positionStart.x));
        this._ref.height(Math.abs(positionEnd.y - positionStart.y));
    }
}

const MarkupMode2Konva = {
    SelectMarkup: {
        name: "SelectMarkup",
        initializer: null
    },
    Line: {
        name: "Line",
        initializer: (ref, params = null, ...attr) => new KonvaLine(params, ref, ...attr)
    },
    Text: {
        name: "Text",
        initializer: (ref, params = null, ...attr) => new KonvaText(params, ref, ...attr)
    },
    Rectangle: {
        name: "Rect",
        initializer: (ref, params = null, ...attr) => new KonvaRectangle(params, ref, ...attr)
    },
    Ellipse: {
        name: "Ellipse",
        initializer: (ref, params = null, ...attr) => new KonvaEllipse(params, ref, ...attr)
    },
    Arrow: {
        name: "Arrow",
        initializer: (ref, params = null, ...attr) => new KonvaArrow(params, ref, ...attr)
    },
    Image: {
        name: "Image",
        initializer: (ref, params = null, ...attr) => new KonvaImage(params, ref, ...attr)
    },
    Cloud: {
        name: "Cloud",
        initializer: (ref, params = null, ...attr) => new KonvaCloud(params, ref, ...attr)
    }
};

function debounce(func, wait) {
    let timeout = null;
    return (...args) => {
        if (timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout((() => {
            timeout = null;
            func(...args);
        }), wait);
    };
}

class KonvaMarkup {
    constructor() {
        this._markupIsActive = false;
        this._markupColor = new MarkupColor(255, 0, 0);
        this.lineWidth = 4;
        this.lineType = "solid";
        this.fontSize = 34;
        this.changeActiveDragger = event => {
            const draggerName = event.data;
            this._markupContainer.className = this._container.className.split(" ").filter((x => !x.startsWith("oda-cursor-"))).filter((x => x)).concat(`oda-cursor-${draggerName.toLowerCase()}`).join(" ");
            this.removeTextInput();
            this.removeImageInput();
            this.enableEditMode(draggerName);
        };
        this.resizeContainer = entries => {
            const {width: width, height: height} = entries[0].contentRect;
            if (!width || !height) return;
            if (!this._konvaStage) return;
            this._konvaStage.width(width);
            this._konvaStage.height(height);
            this.getObjects().forEach((markupObject => {
                markupObject.updateScreenCoordinates();
            }));
        };
        this.resizeViewer = event => {
            const {width: width, height: height} = event;
            if (!width || !height) return;
            if (!this._konvaStage) return;
            this._konvaStage.width(width);
            this._konvaStage.height(height);
            this.getObjects().forEach((markupObject => {
                markupObject.updateScreenCoordinates();
            }));
        };
        this.pan = event => {
            this.getObjects().forEach((markupObject => {
                markupObject.updateScreenCoordinates();
            }));
        };
        this.zoomAt = event => {
            this.getObjects().forEach((markupObject => {
                markupObject.updateScreenCoordinates();
            }));
        };
        this.redirectToViewer = event => {
            if (this._viewer) this._viewer.emit(event);
        };
        this.getRelativePointPosition = (point, node) => {
            const transform = node.getAbsoluteTransform().copy();
            transform.invert();
            return transform.point(point);
        };
        this.getRelativePointerPosition = node => this.getRelativePointPosition(node.getStage().getPointerPosition(), node);
    }
    initialize(container, containerEvents, viewer, worldTransformer) {
        if (!Konva) throw new Error('Markup error: Konva is not initialized. Forgot to add <script src="https://unpkg.com/konva@9/konva.min.js"><\/script> to your page?');
        this._viewer = viewer;
        this._worldTransformer = worldTransformer !== null && worldTransformer !== undefined ? worldTransformer : new WorldTransform;
        this._container = container;
        this._markupContainer = document.createElement("div");
        this._markupContainer.id = "markup-container";
        this._markupContainer.style.position = "absolute";
        this._markupContainer.style.top = "0px";
        this._markupContainer.style.left = "0px";
        this._markupContainer.style.outline = "0px";
        this._markupContainer.style.pointerEvents = "none";
        const parentDiv = this._container.parentElement;
        parentDiv.appendChild(this._markupContainer);
        if (viewer) this._viewer.addEventListener("resize", this.resizeViewer); else this._resizeObserver = new ResizeObserver(debounce(this.resizeContainer, 100));
        this._markupColor.setColor(255, 0, 0);
        this.initializeKonva();
        if (this._viewer) {
            this._viewer.addEventListener("changeactivedragger", this.changeActiveDragger);
            this._viewer.addEventListener("pan", this.pan);
            this._viewer.addEventListener("zoomat", this.zoomAt);
        }
    }
    dispose() {
        var _a, _b;
        if (this._viewer) {
            this._viewer.removeEventListener("zoomat", this.zoomAt);
            this._viewer.removeEventListener("pan", this.pan);
            this._viewer.removeEventListener("changeactivedragger", this.changeActiveDragger);
        }
        this.destroyKonva();
        (_a = this._resizeObserver) === null || _a === undefined ? undefined : _a.disconnect();
        this._resizeObserver = undefined;
        (_b = this._markupContainer) === null || _b === undefined ? undefined : _b.remove();
        this._markupContainer = undefined;
        this._container = undefined;
        this._viewer = undefined;
        this._worldTransformer = undefined;
        this._markupIsActive = false;
    }
    syncOverlay() {}
    clearOverlay() {
        this.removeTextInput();
        this.removeImageInput();
        this.clearSelected();
        this.getObjects().forEach((obj => obj.delete()));
    }
    getMarkupColor() {
        return this._markupColor.asRGB();
    }
    setMarkupColor(r, g, b) {
        this._markupColor.setColor(r, g, b);
        this.redirectToViewer({
            type: "changemarkupcolor",
            data: {
                r: r,
                g: g,
                b: b
            }
        });
    }
    colorizeAllMarkup(r, g, b) {
        const hexColor = new MarkupColor(r, g, b).asHex();
        this.getObjects().filter((obj => {
            var _a;
            return (_a = obj.setColor) === null || _a === undefined ? undefined : _a.call(obj, hexColor);
        }));
    }
    colorizeSelectedMarkups(r, g, b) {
        const hexColor = new MarkupColor(r, g, b).asHex();
        this.getSelectedObjects().filter((obj => {
            var _a;
            return (_a = obj.setColor) === null || _a === undefined ? undefined : _a.call(obj, hexColor);
        }));
    }
    setViewpoint(viewpoint) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        this.clearSelected();
        this.removeTextInput();
        this.removeImageInput();
        this._konvaStage.scale({
            x: 1,
            y: 1
        });
        this._konvaStage.position({
            x: 0,
            y: 0
        });
        const markupColor = ((_a = viewpoint.custom_fields) === null || _a === undefined ? undefined : _a.markup_color) || {
            r: 255,
            g: 0,
            b: 0
        };
        this.setMarkupColor(markupColor.r, markupColor.g, markupColor.b);
        (_b = viewpoint.lines) === null || _b === undefined ? undefined : _b.forEach((line => {
            const linePoints = [];
            line.points.forEach((point => {
                const screenPoint = this._worldTransformer.worldToScreen(point);
                linePoints.push(screenPoint.x);
                linePoints.push(screenPoint.y);
            }));
            this.addLine(linePoints, line.color, line.type, line.width, line.id);
        }));
        (_c = viewpoint.texts) === null || _c === undefined ? undefined : _c.forEach((text => {
            const screenPoint = this._worldTransformer.worldToScreen(text.position);
            this.addText(text.text, screenPoint, text.angle, text.color, text.text_size, text.font_size, text.id);
        }));
        (_d = viewpoint.rectangles) === null || _d === undefined ? undefined : _d.forEach((rect => {
            const screenPoint = this._worldTransformer.worldToScreen(rect.position);
            this.addRectangle(screenPoint, null, rect.width, rect.height, rect.line_width, rect.color, rect.id);
        }));
        (_e = viewpoint.ellipses) === null || _e === undefined ? undefined : _e.forEach((ellipse => {
            const screenPoint = this._worldTransformer.worldToScreen(ellipse.position);
            this.addEllipse(screenPoint, ellipse.radius, ellipse.line_width, ellipse.color, ellipse.id);
        }));
        (_f = viewpoint.arrows) === null || _f === undefined ? undefined : _f.forEach((arrow => {
            const startPoint = this._worldTransformer.worldToScreen(arrow.start);
            const endPoint = this._worldTransformer.worldToScreen(arrow.end);
            this.addArrow(startPoint, endPoint, arrow.color, arrow.id);
        }));
        (_g = viewpoint.clouds) === null || _g === undefined ? undefined : _g.forEach((cloud => {
            const screenPoint = this._worldTransformer.worldToScreen(cloud.position);
            this.addCloud(screenPoint, null, cloud.width, cloud.height, cloud.line_width, cloud.color, cloud.id);
        }));
        (_h = viewpoint.images) === null || _h === undefined ? undefined : _h.forEach((image => {
            const screenPoint = this._worldTransformer.worldToScreen(image.position);
            this.addImage(screenPoint, image.src, image.width, image.height, image.id);
        }));
    }
    getViewpoint(viewpoint) {
        if (!viewpoint) viewpoint = {};
        viewpoint.lines = this.getMarkupLines();
        viewpoint.texts = this.getMarkupTexts();
        viewpoint.arrows = this.getMarkupArrows();
        viewpoint.clouds = this.getMarkupClouds();
        viewpoint.ellipses = this.getMarkupEllipses();
        viewpoint.images = this.getMarkupImages();
        viewpoint.rectangles = this.getMarkupRectangles();
        viewpoint.custom_fields = {
            markup_color: this.getMarkupColor()
        };
        viewpoint.snapshot = {
            data: this.combineMarkupWithDrawing()
        };
        return viewpoint;
    }
    enableEditMode(mode) {
        if (!mode || !MarkupMode2Konva[mode]) {
            this.clearSelected();
            this.removeTextInput();
            this.removeImageInput();
            this._markupContainer.style.pointerEvents = "none";
            this._markupIsActive = false;
        } else {
            this._markupMode = mode;
            this._markupContainer.style.pointerEvents = "all";
            this._markupIsActive = true;
        }
        return this;
    }
    createObject(type, params) {
        const konvaShape = MarkupMode2Konva[type];
        if (!konvaShape || !konvaShape.initializer) throw new Error(`Markup CreateObject - unsupported markup type ${type}`);
        const object = konvaShape.initializer(null, params, this._worldTransformer);
        this.addObject(object);
        return object;
    }
    getObjects() {
        const objects = [];
        Object.keys(MarkupMode2Konva).forEach((type => {
            const konvaShape = MarkupMode2Konva[type];
            this.konvaLayerFind(type).forEach((ref => objects.push(konvaShape.initializer(ref, null, this._worldTransformer))));
        }));
        return objects;
    }
    getSelectedObjects() {
        if (!this._konvaTransformer) return [];
        return this._konvaTransformer.nodes().map((ref => {
            const name = ref.className;
            const konvaShape = Object.values(MarkupMode2Konva).find((shape => shape.name === name));
            return konvaShape ? konvaShape.initializer(ref, null, this._worldTransformer) : null;
        })).filter((x => x));
    }
    selectObjects(objects) {
        if (!this._konvaTransformer) return;
        const selectedObjs = this._konvaTransformer.nodes().concat(objects.map((x => x.ref())));
        this._konvaTransformer.nodes(selectedObjs);
    }
    clearSelected() {
        if (this._konvaTransformer) this._konvaTransformer.nodes([]);
    }
    addObject(object) {
        if (object.type() === "Image") this._groupImages.add(object.ref()); else if (object.type() === "Text") this._groupTexts.add(object.ref()); else this._groupGeometry.add(object.ref());
    }
    konvaLayerFind(type) {
        if (!this._konvaLayer) return [];
        const konvaShape = MarkupMode2Konva[type];
        if (!konvaShape || !konvaShape.initializer) return [];
        return this._konvaLayer.find(konvaShape.name).filter((ref => ref.parent === this._konvaLayer || ref.parent === this._groupImages || ref.parent === this._groupGeometry || ref.parent === this._groupTexts));
    }
    initializeKonva() {
        const stage = new Konva.Stage({
            container: this._markupContainer,
            width: this._container.clientWidth,
            height: this._container.clientHeight
        });
        this._konvaStage = stage;
        const layer = new Konva.Layer({
            pixelRation: window.devicePixelRatio
        });
        stage.add(layer);
        this._groupImages = new Konva.Group;
        layer.add(this._groupImages);
        this._groupGeometry = new Konva.Group;
        layer.add(this._groupGeometry);
        this._groupTexts = new Konva.Group;
        layer.add(this._groupTexts);
        this._konvaLayer = layer;
        const transformer = new Konva.Transformer({
            shouldOverdrawWholeArea: false,
            keepRatio: false,
            flipEnabled: false
        });
        layer.add(transformer);
        this._konvaTransformer = transformer;
        let isPaint = false;
        let lastLine;
        let mouseDownPos;
        let lastObj;
        stage.on("mousedown touchstart", (e => {
            if (!this._markupIsActive || e.target !== stage || this._markupMode === "Text" || this._markupMode === "Image") return;
            if (e.target === stage && transformer.nodes().length > 0) {
                transformer.nodes([]);
                return;
            }
            const pos = this.getRelativePointerPosition(stage);
            mouseDownPos = pos;
            isPaint = [ "Arrow", "Cloud", "Ellipse", "Line", "Rectangle" ].some((m => m === this._markupMode));
            if (this._markupMode === "Line") {
                lastLine = this.addLine([ pos.x, pos.y, pos.x, pos.y ]);
            }
        }));
        stage.on("mouseup touchend", (e => {
            if (!this._markupIsActive) return;
            if (isPaint) {
                const pos = this.getRelativePointerPosition(stage);
                const defParams = mouseDownPos && pos.x === mouseDownPos.x && pos.y === mouseDownPos.y;
                const startX = defParams ? mouseDownPos.x : Math.min(mouseDownPos.x, pos.x);
                const startY = defParams ? mouseDownPos.y : Math.min(mouseDownPos.y, pos.y);
                const dX = defParams ? 200 : Math.abs(mouseDownPos.x - pos.x);
                const dY = defParams ? 200 : Math.abs(mouseDownPos.y - pos.y);
                if (defParams) {
                    if (this._markupMode === "Rectangle") {
                        this.addRectangle({
                            x: startX,
                            y: startY
                        }, null, dX, dY);
                    } else if (this._markupMode === "Ellipse") {
                        this.addEllipse({
                            x: startX,
                            y: startY
                        }, {
                            x: dX / 2,
                            y: dY / 2
                        });
                    } else if (this._markupMode === "Arrow") {
                        this.addArrow({
                            x: mouseDownPos.x,
                            y: mouseDownPos.y
                        }, {
                            x: defParams ? mouseDownPos.x + 200 : pos.x,
                            y: defParams ? startY : pos.y
                        });
                    } else if (this._markupMode === "Cloud") {
                        this.addCloud({
                            x: startX,
                            y: startY
                        }, null, Math.max(100, dX), Math.max(100, dY));
                    }
                }
            }
            lastObj = undefined;
            isPaint = false;
        }));
        stage.on("mousemove touchmove", (e => {
            if (!this._markupIsActive) return;
            if (!isPaint) {
                return;
            }
            const pos = this.getRelativePointerPosition(stage);
            const defParams = mouseDownPos && pos.x === mouseDownPos.x && pos.y === mouseDownPos.y;
            const startX = defParams ? mouseDownPos.x : Math.min(mouseDownPos.x, pos.x);
            const startY = defParams ? mouseDownPos.y : Math.min(mouseDownPos.y, pos.y);
            const dX = defParams ? 200 : Math.abs(mouseDownPos.x - pos.x);
            const dY = defParams ? 200 : Math.abs(mouseDownPos.y - pos.y);
            if (this._markupMode === "Line") {
                lastLine.addPoints([ {
                    x: pos.x,
                    y: pos.y
                } ]);
            } else if (this._markupMode === "Arrow") {
                if (lastObj) lastObj.setEndPoint(pos.x, pos.y); else lastObj = this.addArrow({
                    x: mouseDownPos.x,
                    y: mouseDownPos.y
                }, {
                    x: pos.x,
                    y: pos.y
                });
            } else if (this._markupMode === "Rectangle") {
                if (lastObj) {
                    lastObj.setPosition(startX, startY);
                    lastObj.setWidth(dX);
                    lastObj.setHeight(dY);
                } else lastObj = this.addRectangle({
                    x: startX,
                    y: startY
                }, null, dX, dY);
            } else if (this._markupMode === "Ellipse") {
                if (lastObj) {
                    lastObj.setPosition(startX, startY);
                    lastObj.setRadiusX(dX);
                    lastObj.setRadiusY(dY);
                } else lastObj = this.addEllipse({
                    x: startX,
                    y: startY
                }, {
                    x: dX,
                    y: dY
                });
            } else if (this._markupMode === "Cloud") {
                if (lastObj) {
                    lastObj.setPosition(startX, startY);
                    lastObj.setWidth(Math.max(100, dX));
                    lastObj.setHeight(Math.max(100, dY));
                } else lastObj = this.addCloud({
                    x: startX,
                    y: startY
                }, null, dX, dY);
            }
        }));
        stage.on("click tap", (e => {
            if (!this._markupIsActive) return;
            if (e.target === stage) {
                if (this._markupMode === "Text") {
                    if (this._textInputRef && this._textInputRef.value) this.addText(this._textInputRef.value, this._textInputPos, this._textInputAngle); else if (transformer.nodes().length === 0) {
                        const pos = this.getRelativePointerPosition(stage);
                        this.createTextInput(pos, e.evt.pageX, e.evt.pageY, 0, null);
                    }
                } else if (this._markupMode === "Image") {
                    if (this._imageInputRef && this._imageInputRef.value) this.addImage({
                        x: this._imageInputPos.x,
                        y: this._imageInputPos.y
                    }, this._imageInputRef.value, 0, 0, this._imageInputRef.value); else if (transformer.nodes().length === 0) {
                        const pos = this.getRelativePointerPosition(stage);
                        this.createImageInput(pos);
                    }
                }
                transformer.nodes([]);
                return;
            }
            if (this._markupMode === "Text" || this._markupMode === "SelectMarkup") {
                if (e.target.className === "Text" && transformer.nodes().length === 1 && transformer.nodes()[0] === e.target) {
                    if (this._textInputRef && this._textInputRef.value) this.addText(this._textInputRef.value, this._textInputPos, this._textInputAngle); else this.createTextInput({
                        x: e.target.attrs.x,
                        y: e.target.attrs.y
                    }, e.evt.pageX, e.evt.pageY, e.target.attrs.rotation, e.target.attrs.text);
                    return;
                } else {
                    this.removeTextInput();
                }
            }
            if (this._markupMode === "Image" || this._markupMode === "SelectMarkup") {
                if (e.target.className === "Image" && transformer.nodes().length === 1 && transformer.nodes()[0] === e.target) {
                    if (this._imageInputRef && this._imageInputRef.value) this.addImage(this._imageInputPos, this._imageInputRef.value, 0, 0); else this.createImageInput({
                        x: e.target.attrs.x,
                        y: e.target.attrs.y
                    });
                    return;
                } else {
                    this.removeImageInput();
                }
            }
            if (transformer.nodes().filter((x => x.className === "Cloud" || x.className === "Image")).length > 0 || e.target.className === "Cloud" || e.target.className === "Image") {
                transformer.rotateEnabled(false);
            } else {
                transformer.rotateEnabled(true);
            }
            const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
            const isSelected = transformer.nodes().indexOf(e.target) >= 0;
            if (!metaPressed && !isSelected) {
                transformer.nodes([ e.target ]);
            } else if (metaPressed && isSelected) {
                const nodes = transformer.nodes().slice();
                nodes.splice(nodes.indexOf(e.target), 1);
                transformer.nodes(nodes);
            } else if (metaPressed && !isSelected) {
                const nodes = transformer.nodes().concat([ e.target ]);
                transformer.nodes(nodes);
            }
        }));
        const container = stage.container();
        container.tabIndex = 1;
        container.focus();
        container.addEventListener("keydown", (e => {
            if (!this._markupIsActive) return;
            if (e.code === "Delete") {
                this.getSelectedObjects().forEach((obj => obj.delete()));
                this.clearSelected();
                return;
            }
            e.preventDefault();
        }));
    }
    destroyKonva() {
        var _a;
        this.removeTextInput();
        this.removeImageInput();
        this.clearOverlay();
        (_a = this._konvaStage) === null || _a === undefined ? undefined : _a.destroy();
        this._groupImages = undefined;
        this._groupGeometry = undefined;
        this._groupTexts = undefined;
        this._konvaLayer = undefined;
        this._konvaTransformer = undefined;
        this._konvaStage = undefined;
    }
    getMarkupLines() {
        const lines = [];
        this.konvaLayerFind("Line").forEach((ref => {
            const wcsPoints = ref.getAttr("wcsPoints");
            if (!wcsPoints) return;
            const konvaLine = new KonvaLine(null, ref, this._worldTransformer);
            const line = {
                id: konvaLine.id(),
                points: wcsPoints,
                color: konvaLine.getColor() || "#ff0000",
                type: konvaLine.getLineType() || this.lineType,
                width: konvaLine.getLineWidth() || this.lineWidth
            };
            lines.push(line);
        }));
        return lines;
    }
    getMarkupTexts() {
        const texts = [];
        this.konvaLayerFind("Text").forEach((ref => {
            const textSize = .02;
            const textScale = this._worldTransformer.getScale();
            const wcsPosition = ref.getAttr("wcsStart");
            const stageAbsoluteTransform = this._konvaStage.getAbsoluteTransform();
            const shape = new KonvaText(null, ref, this._worldTransformer);
            const text = {
                id: shape.id(),
                position: wcsPosition,
                text: shape.getText(),
                text_size: textSize * textScale.y,
                angle: shape.getRotation(),
                color: shape.getColor(),
                font_size: shape.getFontSize() * stageAbsoluteTransform.getMatrix()[0]
            };
            texts.push(text);
        }));
        return texts;
    }
    getMarkupRectangles() {
        const rectangles = [];
        this.konvaLayerFind("Rectangle").forEach((ref => {
            const wcsStart = ref.getAttr("wcsStart");
            const wcsEnd = ref.getAttr("wcsEnd");
            const screenStart = this._worldTransformer.worldToScreen(wcsStart);
            const screenEnd = this._worldTransformer.worldToScreen(wcsEnd);
            const shape = new KonvaRectangle(null, ref, this._worldTransformer);
            const rectangle = {
                id: shape.id(),
                position: wcsStart,
                width: Math.abs(screenStart.x - screenEnd.x),
                height: Math.abs(screenStart.y - screenEnd.y),
                line_width: shape.getLineWidth(),
                color: shape.getColor()
            };
            rectangles.push(rectangle);
        }));
        return rectangles;
    }
    getMarkupEllipses() {
        const ellipses = [];
        this.konvaLayerFind("Ellipse").forEach((ref => {
            const wcsPosition = ref.getAttr("wcsPosition");
            const stageAbsoluteTransform = this._konvaStage.getAbsoluteTransform();
            const scale = stageAbsoluteTransform.getMatrix()[0];
            const shape = new KonvaEllipse(null, ref, this._worldTransformer);
            const ellipse = {
                id: shape.id(),
                position: wcsPosition,
                radius: {
                    x: ref.getRadiusX() * scale,
                    y: ref.getRadiusY() * scale
                },
                line_width: shape.getLineWidth(),
                color: shape.getColor()
            };
            ellipses.push(ellipse);
        }));
        return ellipses;
    }
    getMarkupArrows() {
        const arrows = [];
        this.konvaLayerFind("Arrow").forEach((ref => {
            const wcsStart = ref.getAttr("wcsStart");
            const wcsEnd = ref.getAttr("wcsEnd");
            const shape = new KonvaArrow(null, ref, this._worldTransformer);
            const arrow = {
                id: shape.id(),
                start: wcsStart,
                end: wcsEnd,
                color: shape.getColor()
            };
            arrows.push(arrow);
        }));
        return arrows;
    }
    getMarkupImages() {
        const images = [];
        this.konvaLayerFind("Image").forEach((ref => {
            const wcsStart = ref.getAttr("wcsStart");
            const stageAbsoluteTransform = this._konvaStage.getAbsoluteTransform();
            const scale = stageAbsoluteTransform.getMatrix()[0];
            const shape = new KonvaImage(null, ref, this._worldTransformer);
            const image = {
                id: shape.id(),
                position: wcsStart,
                src: shape.getSrc(),
                width: shape.getWidth() * scale,
                height: shape.getHeight() * scale
            };
            images.push(image);
        }));
        return images;
    }
    getMarkupClouds() {
        const clouds = [];
        this.konvaLayerFind("Cloud").forEach((ref => {
            const wcsStart = ref.getAttr("wcsStart");
            const wcsEnd = ref.getAttr("wcsEnd");
            const screenStart = this._worldTransformer.worldToScreen(wcsStart);
            const screenEnd = this._worldTransformer.worldToScreen(wcsEnd);
            const shape = new KonvaCloud(null, ref, this._worldTransformer);
            const cloud = {
                id: shape.id(),
                position: wcsStart,
                width: Math.abs(screenStart.x - screenEnd.x),
                height: Math.abs(screenStart.y - screenEnd.y),
                line_width: shape.getLineWidth(),
                color: shape.getColor()
            };
            clouds.push(cloud);
        }));
        return clouds;
    }
    combineMarkupWithDrawing() {
        this.clearSelected();
        const tempCanvas = document.createElement("canvas");
        if (this._konvaStage) {
            tempCanvas.width = this._konvaStage.width();
            tempCanvas.height = this._konvaStage.height();
            const ctx = tempCanvas.getContext("2d");
            if (this._container instanceof HTMLCanvasElement) ctx.drawImage(this._container, 0, 0);
            ctx.drawImage(this._konvaStage.toCanvas({
                pixelRatio: window.devicePixelRatio
            }), 0, 0);
        }
        return tempCanvas.toDataURL("image/jpeg", .25);
    }
    addLine(linePoints, color, type, width, id) {
        if (!linePoints || linePoints.length === 0) return;
        const points = [];
        for (let i = 0; i < linePoints.length; i += 2) {
            points.push({
                x: linePoints[i],
                y: linePoints[i + 1]
            });
        }
        const konvaLine = new KonvaLine({
            points: points,
            type: type || this.lineType,
            width: width || this.lineWidth,
            color: color || this._markupColor.asHex(),
            id: id
        }, null, this._worldTransformer);
        this.addObject(konvaLine);
        return konvaLine;
    }
    createTextInput(pos, inputX, inputY, angle, text) {
        if (!this._textInputRef) {
            this._textInputPos = pos;
            this._textInputAngle = angle;
            this._textInputRef = document.createElement("textarea");
            this._textInputRef.style.zIndex = "9999";
            this._textInputRef.style.position = "absolute";
            this._textInputRef.style.display = "block";
            this._textInputRef.style.top = inputY + "px";
            this._textInputRef.style.left = inputX + "px";
            this._textInputRef.style.fontSize = `${this.fontSize}px`;
            this._textInputRef.style.color = `${this._markupColor.asHex()}`;
            this._textInputRef.style.fontFamily = "Calibri";
            this._textInputRef.onkeydown = event => {
                if (event.key === "Enter" && !event.shiftKey) {
                    event.preventDefault();
                    this.addText(this._textInputRef.value, this._textInputPos, this._textInputAngle);
                }
                if (event.key === "Escape") {
                    event.preventDefault();
                    this.removeTextInput();
                }
            };
            if (text) this._textInputRef.value = text;
            document.body.appendChild(this._textInputRef);
            setTimeout((() => {
                this._textInputRef.focus();
            }), 50);
        } else {
            this.removeTextInput();
        }
    }
    removeTextInput() {
        var _a;
        (_a = this._textInputRef) === null || _a === undefined ? undefined : _a.remove();
        this._textInputRef = null;
        this._textInputPos = null;
        this._textInputAngle = 0;
    }
    createImageInput(pos) {
        if (!this._imageInputRef) {
            const convertBase64 = file => new Promise(((resolve, reject) => {
                const fileReader = new FileReader;
                fileReader.readAsDataURL(file);
                fileReader.onload = () => {
                    resolve(fileReader.result);
                };
                fileReader.onerror = error => {
                    reject(error);
                };
            }));
            this._imageInputPos = pos;
            this._imageInputRef = document.createElement("input");
            this._imageInputRef.style.display = "none";
            this._imageInputRef.type = "file";
            this._imageInputRef.accept = "image/png, image/jpeg";
            this._imageInputRef.onchange = async event => {
                const file = event.target.files[0];
                const base64 = await convertBase64(file);
                this.addImage({
                    x: this._imageInputPos.x,
                    y: this._imageInputPos.y
                }, base64.toString(), 0, 0);
            };
            this._imageInputRef.oncancel = event => {
                this.removeImageInput();
            };
            document.body.appendChild(this._imageInputRef);
            setTimeout((() => {
                this._imageInputRef.click();
            }), 50);
        } else {
            this.removeImageInput();
        }
    }
    removeImageInput() {
        var _a;
        (_a = this._imageInputRef) === null || _a === undefined ? undefined : _a.remove();
        this._imageInputRef = null;
        this._imageInputPos = null;
    }
    addText(text, position, angle, color, textSize, fontSize, id) {
        var _a;
        if (!text) return;
        (_a = this.getSelectedObjects().at(0)) === null || _a === undefined ? undefined : _a.delete();
        this.clearSelected();
        this.removeTextInput();
        const tolerance = 1e-6;
        if (textSize && textSize > tolerance && (!fontSize || fontSize < tolerance)) {
            const size = .02;
            const scale = this._worldTransformer.getScale();
            fontSize = textSize / (scale.y / size) / 34;
        }
        const konvaText = new KonvaText({
            position: {
                x: position.x,
                y: position.y
            },
            text: text,
            rotation: angle,
            fontSize: fontSize || this.fontSize,
            color: color || this._markupColor.asHex(),
            id: id
        }, null, this._worldTransformer);
        this.addObject(konvaText);
        return konvaText;
    }
    addRectangle(position, position2, width, height, lineWidth, color, id) {
        if (!position) return;
        const konvaRectangle = new KonvaRectangle({
            position: position,
            position2: position2,
            width: width,
            height: height,
            lineWidth: lineWidth || this.lineWidth,
            color: color || this._markupColor.asHex(),
            id: id
        }, null, this._worldTransformer);
        this.addObject(konvaRectangle);
        return konvaRectangle;
    }
    addEllipse(position, radius, lineWidth, color, id) {
        if (!position) return;
        const konvaEllipse = new KonvaEllipse({
            position: position,
            radius: radius,
            lineWidth: lineWidth,
            color: color || this._markupColor.asHex(),
            id: id
        }, null, this._worldTransformer);
        this.addObject(konvaEllipse);
        return konvaEllipse;
    }
    addArrow(start, end, color, id) {
        if (!start || !end) return;
        const konvaArrow = new KonvaArrow({
            start: start,
            end: end,
            color: color || this._markupColor.asHex(),
            id: id
        }, null, this._worldTransformer);
        this.addObject(konvaArrow);
        return konvaArrow;
    }
    addCloud(position, position2, width, height, lineWidth, color, id) {
        if (!position || !width || !height) return;
        const konvaCloud = new KonvaCloud({
            position: position,
            position2: position2,
            width: width,
            height: height,
            color: color || this._markupColor.asHex(),
            lineWidth: lineWidth || this.lineWidth,
            id: id
        }, null, this._worldTransformer);
        this.addObject(konvaCloud);
        return konvaCloud;
    }
    addImage(position, src, width, height, id) {
        var _a;
        if (!position || !src) return;
        (_a = this.getSelectedObjects().at(0)) === null || _a === undefined ? undefined : _a.delete();
        this.clearSelected();
        this.removeImageInput();
        const konvaImage = new KonvaImage({
            position: position,
            src: src,
            width: width,
            height: height,
            maxWidth: this._konvaStage.width() - position.x,
            maxHeight: this._konvaStage.height() - position.y,
            id: id
        }, null, this._worldTransformer);
        this.addObject(konvaImage);
        return konvaImage;
    }
}

export { KonvaMarkup as Markup };
//# sourceMappingURL=markup.module.js.map