UNPKG

@sfgrp/svg-detailer

Version:

A dependency free javascript library for annotating images, with results exportable as SVG elements.

1,303 lines 82.6 kB
var st = Object.defineProperty; var it = (s, t, i) => t in s ? st(s, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : s[t] = i; var D = (s, t, i) => (it(s, typeof t != "symbol" ? t + "" : t, i), i); const S = { ARROWS_SPECS: "arrowspecs", COLOR: "colorselect", FONT_SIZE: "fontsize", JSON: "json", LOCK: "lock", MODE: "mode", NEWLINE: "newline", RESET: "reset", UNLOCK: "unlock", ZOOM: "zoom", ZOOM_IN: "zoomin", ZOOM_OUT: "zoomout" }, a = { ARROW: "arrow", CIRCLE: "circle", CLEAR: "clear", CUBIC: "cubic", DRAW: "draw", ELLIPSE: "ellipse", LINE: "line", MOVE: "move", POLYGON: "polygon", POLYLINE: "polyline", QUADRATIC: "quadratic", RECTANGLE: "rect", TEXT: "text", ERASER: "eraser" }, C = { ALT: "Alt", ARROW_DOWN: "ArrowDown", ARROW_LEFT: "ArrowLeft", ARROW_RIGHT: "ArrowRigt", ARROW_UP: "ArrowUp", BACKSPACE: "Backspace", CAPS_LOCK: "CapsLock", CONTROL: "Control", DELETE: "Delete", ENTER: "Enter", ESC: "Escape", META_LEFT: "MetaLeft", META_RIGHT: "MetaRight", SHIFT_LEFT: "ShiftLeft", SHIFT_RIGHT: "ShiftRight", SPACE: "Space", TAB: "Tab", B: "KeyB", T: "KeyT" }, rt = { 61: "=", 106: "*", 107: "+", 109: "-", 110: ".", 111: "/", 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'" }, w = { "`": "~", 1: "!", 2: "@", 3: "#", 4: "$", 5: "%", 6: "^", 7: "&", 8: "*", 9: "(", 0: ")", "-": "_", "=": "+", ";": ":", "'": '"', "[": "{", "]": "}", ",": "<", ".": ">", "/": "?", "\\": "|" }, b = { CIRCLE: "circle", CUBIC: "cubic", ELLIPSE: "ellipse", GROUP: "g", IMAGE: "image", LINE: "line", PATH: "path", POLYGON: "polygon", POLYLINE: "polyline", QUADRATIC: "quadratic", RECT: "rect", SVG: "svg", TEXT: "text" }; function P(s, t = {}) { const i = document.createElement(s); return Object.entries(t).forEach(([e, r]) => { i.setAttribute(e, r); }), i; } function v({ label: s, attr: t = {}, event: i = {} }) { const e = Object.entries(i), r = P("input", { type: "text", ...t }); if (e.forEach(([n, u]) => { r.addEventListener(n, u); }), s) { const n = P("label"); return n.innerHTML = s, n.appendChild(r), n; } else return r; } function nt(s) { const t = P("span", { innerHTML: "Arrowhead: " }), i = v({ label: "Close", attr: { type: "checkbox" }, event: { change: (u) => s.apiArrowClosed(u.target.value) } }), e = v({ label: "Fixed", attr: { type: "checkbox" }, event: { change: (u) => s.apiArrowFixed(u.target.value) } }), r = v({ label: "Length", attr: { type: "number", value: 50, style: "width: 4em" }, event: { change: (u) => s.configuration.arrowheadLength = u.target.value } }), n = v({ label: "Percent", attr: { type: "number", value: 10, min: 5, step: 1, max: 30, style: "width: 4em" }, event: { change: (u) => s.configuration.arrowPercent = u.target.value } }); return t.innerHTML = "Arrowhead: ", t.appendChild(i), t.appendChild(e), t.appendChild(r), t.appendChild(n), t; } function at(s) { return v({ label: "Select color: ", attr: { type: "color", value: "#000000" }, event: { change: (i) => { s.apiStroke(i.target.value); } } }); } function ut(s) { return v({ label: " Font Size: ", attr: { type: "number", min: 5, step: 5, max: 300, style: "width: 4em", value: s.configuration.fontSize }, event: { input: (i) => { s.configuration.fontSize = i.target.value; } } }); } function ot(s) { const t = P("span"), i = P("textarea", { rows: 5 }), e = v({ attr: { type: "button", value: "Extract SVG" }, event: { click: () => i.innerHTML = s.apiShowSVG(!0) } }), r = v({ attr: { type: "button", value: "Plain SVG" }, event: { click: () => i.innerHTML = s.apiShowSVG(!1) } }), n = v({ attr: { type: "button", value: "Bare SVG" }, event: { click: () => i.innerHTML = s.apiBareSVG() } }), u = v({ attr: { type: "button", value: "JSON SVG" }, event: { click: () => i.innerHTML = JSON.stringify(s.apiJsonSVG()) } }); return t.appendChild(e), t.appendChild(r), t.appendChild(n), t.appendChild(u), t.appendChild(P("br")), t.appendChild(i), t; } function lt(s) { const { containerElement: t } = s; if (t.attributes["data-buttons"]) { const i = JSON.parse( t.attributes["data-buttons"].value ).buttons, e = P("div"); t.parentElement.appendChild(e), i.forEach((r) => { const n = r.function; let u; switch (n) { case a.CLEAR: case a.POLYGON: case a.POLYLINE: case a.LINE: case a.ARROW: case a.RECTANGLE: case a.CIRCLE: case a.ELLIPSE: case a.QUADRATIC: case a.CUBIC: case a.DRAW: case a.TEXT: case a.MOVE: case a.ERASER: case S.RESET: u = v({ attr: { type: "button", value: r.value || n.charAt(0).toUpperCase() + n.slice(1) }, event: { click: () => { s.apiSetMode(n); } } }); break; case S.MODE: u = P("span", { id: "mode " }); break; case S.ZOOM: u = P("span", { id: "zoom" }), u.innerHTML = "Zoom: ----"; break; case S.ZOOM_IN: u = v({ attr: { type: "button", value: "Zoom IN" }, event: { click: (l) => { l.target.blur(), s.apiZoomIn(); } } }); break; case S.ZOOM_OUT: u = v({ attr: { type: "button", value: "Zoom OUT" }, event: { click: () => { s.apiZoomOut(); } } }); break; case S.FONT_SIZE: u = ut(s); break; case S.NEWLINE: u = P("br"); break; case S.COLOR: u = at(s); break; case S.ARROWS_SPECS: u = nt(s); break; case S.JSON: u = ot(s); break; } u && e.appendChild(u); }); } } class ht { constructor() { D(this, "events", {}); } on(t, i) { return typeof this.events[t] != "object" && (this.events[t] = []), this.events[t].push(i), () => this.removeListener(t, i); } removeListener(t, i) { if (typeof this.events[t] != "object") return; const e = this.events[t].indexOf(i); e > -1 && this.events[t].splice(e, 1); } removeAllListeners() { Object.keys(this.events).forEach( (t) => this.events[t].splice(0, this.events[t].length) ); } emit(t, ...i) { typeof this.events[t] == "object" && [...this.events[t]].forEach((e) => e.apply(this, i)); } once(t, i) { const e = this.on(t, (...r) => { e(), i.apply(this, r); }); return e; } } function ct(s, { stroke: t, strokeWidth: i, fill: e, fillOpacity: r, strokeOpacity: n, strokeLinecap: u }) { const l = document.createElementNS("http://www.w3.org/2000/svg", s); return l.setAttributeNS(null, "stroke", t), l.setAttributeNS(null, "stroke-width", i), l.setAttributeNS(null, "stroke-opacity", n), l.setAttributeNS(null, "fill", e), l.setAttributeNS(null, "fill-opacity", r), l.setAttributeNS(null, "stroke-linecap", u), l; } function dt(s) { switch (s) { case b.POLYLINE: return { points: 1 }; case b.POLYGON: return { points: 1 }; case b.RECT: return { x: 0, y: 0, width: 1, height: 1 }; case b.LINE: return { x1: 0, y1: 0, x2: 1, y2: 1 }; case b.CIRCLE: return { cx: 0, cy: 0, r: 1 }; case b.ELLIPSE: return { cx: 0, cy: 0, rx: 1, ry: 1 }; case b.PATH: return { x1: 0, y1: 0, xc1: 1, yc1: 1, xc2: 1, yc2: 1, x2: 0, y2: 0 }; case b.TEXT: return { x: 0, y: 0 }; } } const pt = /Mac/.test(navigator.platform); function U({ x: s, y: t, mode: i, attributes: e }) { const r = document.createElementNS("http://www.w3.org/2000/svg", b.GROUP), n = ct(b.LINE, e); return r.setAttributeNS(null, "class", i), n.setAttributeNS(null, "x1", s.toFixed(4)), n.setAttributeNS(null, "y1", t.toFixed(4)), n.setAttributeNS(null, "x2", s.toFixed(4)), n.setAttributeNS(null, "y2", t.toFixed(4)), r.appendChild(n), { group: r, element: n }; } class d extends ht { constructor(t, i = {}) { super(), this.containerElement = t, this.configuration = { arrowClosed: !1, arrowFixed: !1, arrowPercent: 10, // default arrow head size 10 percent of arrow length in pixels arrowheadLength: 50, fontSize: 50, fontFamily: "Verdana", stroke: "#000000", strokeWidth: 1, strokeOpacity: 0.9, fill: "", fillOpacity: 0, strokeLinecap: "round", baseZoom: 0, // calculated from svg and image attributes maxZoom: 4, zoomDelta: 0.02, // this can be altered to discriminate legacy firefox dommousescroll event debugLog: !1, ...i }, this.state = { mousePosition: { x: 0, y: 0 }, mousePositionStart: { x: 0, y: 0 }, xC: 0, yC: 0, zoom: 0, currentKey: void 0, currentGroup: void 0, currentElement: void 0, currentSVGPoints: [], currentBubble: void 0, bubbleRadius: void 0, baseBubbleRadius: 6, waitElement: !1, svgInProgress: !1, svgLayer: void 0, svgImage: void 0, cWidth: 0, cHeight: 0, groupIdCount: 0, capsLock: !1, text: "_", cursorMode: a.MOVE }, this.state.cWidth = parseInt( i.width || t.attributes["data-width"].value ), this.state.cHeight = parseInt( i.height || t.attributes["data-height"].value ), this.handleMouseEnterFunction = this.mouseEnterFunction.bind(this), this.handleMouseLeaveFunction = this.mouseLeaveFunction.bind(this), this.handleMouseClickFunction = this.mouseClickFunction.bind(this), this.handleKeyHandler = this.keyHandler.bind(this), this.handleKeyUpHandler = this.keyUpHandler.bind(this); const e = document.createElementNS( "http://www.w3.org/2000/svg", "svg" ); e.setAttributeNS(null, "id", "svgLayer"), e.setAttribute("xmlns", "http://www.w3.org/2000/svg"), e.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"), e.setAttributeNS(null, "version", "1.1"), e.setAttributeNS(null, "style", "position: inherit;"), e.setAttributeNS(null, "width", this.state.cWidth), e.setAttributeNS(null, "height", this.state.cHeight), this.containerElement.appendChild(e), this.state.svgLayer = e; let r = document.createElementNS( "http://www.w3.org/2000/svg", b.GROUP ); this.xlt = r, e.appendChild(r), this.state.currentSVGPoints = []; const n = i.imageSrc || t.attributes["data-image"].value; if (!n) throw "Missing image src"; this.loadImage(n), i.svg && this.apiLoadSVG(i.svg), lt(this), document.addEventListener("keydown", this.handleKeyHandler), document.addEventListener("keyup", this.handleKeyUpHandler), this.updateCursorMode(a.MOVE), this.renderFunction = this.updateSvgByElement, this.touchSupported = "ontouchstart" in document.documentElement, this.containerID = t, this.state.mousePosition = { x: 0, y: 0 }, this.touchSupported || this.state.svgLayer.addEventListener( "dblclick", this.doubleClickHandler.bind(this) ), this.state.svgLayer.addEventListener( "mousedown", this.onSvgMouseDown.bind(this) ), this.state.svgLayer.addEventListener( "mouseup", this.onSvgMouseUp.bind(this) ), this.state.svgLayer.addEventListener( "mousemove", this.onSvgMouseMove.bind(this) ); } loadImage(t) { this.state.svgImage = new Image(), this.state.svgImage.src = t, this.state.svgImage.onload = () => { this.state.xC = 0, this.state.yC = 0; var i = this.state.cWidth / this.state.cHeight, e = this.state.svgImage.width / this.state.svgImage.height; (i >= 1 && e >= 1 || i <= 1 && e <= 1) && e <= i || e <= 1 && i >= 1 ? this.configuration.baseZoom = this.state.svgLayer.height.baseVal.value / this.state.svgImage.height : this.configuration.baseZoom = this.state.svgLayer.width.baseVal.value / this.state.svgImage.width, this.state.bubbleRadius = (this.state.baseBubbleRadius / this.configuration.baseZoom).toString(), this.state.mousePosition.x = this.configuration.baseZoom * this.state.svgImage.width / 2, this.state.mousePosition.y = this.configuration.baseZoom * this.state.svgImage.height / 2, this.xlt.setAttributeNS(null, "id", "xlt"), this.xlt.setAttributeNS( null, "transform", "translate(0,0) scale(" + parseFloat(this.configuration.baseZoom) + ")" ); const r = document.createElementNS( "http://www.w3.org/2000/svg", b.IMAGE ); r.setAttributeNS(null, "id", "xltImage"), r.setAttributeNS(null, "x", "0"), r.setAttributeNS(null, "y", "0"), r.setAttributeNS( null, "width", this.state.svgImage.width.toString() ), r.setAttributeNS( null, "height", this.state.svgImage.height.toString() ), r.setAttributeNS(null, "preserveAspectRatio", "none"), r.setAttributeNS( "http://www.w3.org/1999/xlink", "href", this.state.svgImage.src ), this.zoom_trans(0, 0, this.configuration.baseZoom), this.xltImage = r, this.xlt.prepend(r); }; } get currentMouseX() { return (this.state.mousePosition.x - this.state.xC) / this.state.zoom; } get currentMouseY() { return (this.state.mousePosition.y - this.state.yC) / this.state.zoom; } setCursorMode(t) { this.state.cursorMode = t, this.emit("changemode", { mode: this.state.cursorMode }); } updateCursorMode(t) { this.state.currentElement && (this.checkLeftoverElement(), this.clearEditElement(this.state.currentGroup)), this.setCursorMode(t), this.state.cursorMode !== a.MOVE && (this.state.cursorMode, a.TEXT, t == a.CLEAR && (this.clearLastGroup(), this.state.cursorMode = a.MOVE), t == S.RESET && (this.setZoom(this.configuration.baseZoom), this.state.cursorMode = a.MOVE), this.state.waitElement = !0), this.state.svgInProgress = !1; } exitEditPoint(t) { for (; t.childElementCount > 1 && t.lastChild.tagName == b.GROUP; ) t.lastChild.remove(); this.state.svgInProgress = !1, this.state.currentBubble = null, this.updateCursorMode(a.MOVE), this.setElementMouseEnterLeave(t); } getIDcount() { return this.state.groupIdCount += 1, this.state.groupIdCount; } zoom_trans(t, i, e) { const r = `translate(${t.toString()}, ${i.toString()}) scale(${e.toString()})`; this.state.zoom = e, this.state.xC = t, this.state.yC = i, this.xlt.attributes.transform.value = r; } zoomIn(t) { const { zoomDelta: i, maxZoom: e } = this.configuration; if (this.state.zoom < e) { let r = this.state.zoom * (1 + (t || i)); r > e && (r = e), this.setZoom(r); } } zoomOut(t) { const { baseZoom: i, zoomDelta: e } = this.configuration; if (this.state.zoom > i / 3) { const r = this.state.zoom / (1 + (t || e)); this.setZoom(r); } } setZoom(t) { this.state.xC = this.state.mousePosition.x - (this.state.mousePosition.x - this.state.xC) * t / this.state.zoom, this.state.yC = this.state.mousePosition.y - (this.state.mousePosition.y - this.state.yC) * t / this.state.zoom, this.zoom_trans(this.state.xC, this.state.yC, t), this.state.zoom = t, this.state.bubbleRadius = (this.state.baseBubbleRadius / this.state.zoom).toString(); } setStroke(t) { this.configuration.stroke = t; } apiFontSize(t) { x(t) && (this.configuration.fontSize = t); } apiFontFamily(t) { this.configuration.fontFamily = t; } apiArrowClosed(t) { this.arrowClosed = t; } apiArrowFixed(t) { this.arrowFixed = t; } apiArrowLength(t) { x(t) && (this.configuration.arrowheadLength = t); } apiArrowPercent(t) { x(t) && (this.configuration.arrowPercent = t); } apiStroke(t) { this.setStroke(t); } apiClearAll() { this.state.groupIdCount = 0, [...this.xlt.querySelectorAll("g")].forEach((i) => i.remove()); } apiStrokeWidth(t) { x(t) && (this.configuration.strokeWidth = t); } apiStrokeOpacity(t) { t >= 0 && t <= 1 && (this.configuration.strokeOpacity = t); } apiStrokeLinecap(t) { this.configuration.strokeLinecap = t; } apiFill(t) { this.configuration.fill = t; } apiFillOpacity(t) { t >= 0 && t <= 1 && (this.configuration.fillOpacity = t.toString()); } apiZoomIn(t) { this.zoomIn(t); } apiZoomOut(t) { this.zoomOut(t); } apiSetZoom(t) { this.setZoom(t); } apiDeleteLast() { this.clearLastGroup(); } apiDeleteHover(t) { t && this.clearThisGroup(t); } apiShowSVG(t) { return K(t, { svgLayer: this.state.svgLayer }).outerHTML; } apiBareSVG(t = !0) { return Ct(t, { svgLayer: this.state.svgLayer }).outerHTML; } apiJsonSVG(t) { const i = K(!1, { svgLayer: this.state.svgLayer, ...t }).firstChild; return i.removeAttribute("id"), i.removeAttribute("transform"), { data: { type: "svg", attributes: i.outerHTML } }; } apiRemoveGroup(t) { [...this.xlt.querySelectorAll(`#${t}`)].forEach((e) => this.removeShape(e)); } apiRemoveLayer(t) { [...this.xlt.querySelectorAll(`[layer-id="${t}"]`)].forEach((e) => this.removeShape(e)); } removeShape(t) { t.remove(); } lockShape(t) { const i = t.querySelector(".bubbles"); this.removeGroupEvents(t), i == null || i.remove(), t.setAttribute("locked", "true"); } unlockShape(t) { this.setElementMouseEnterLeave(t), t.matches(":hover") && this.handleMouseEnterFunction({ target: t }), t.setAttribute("locked", "false"); } unlockLayer(t) { [ ...this.xlt.querySelectorAll(`[layer-id="${t}"][locked="true"]`) ].forEach((e) => this.unlockShape(e)); } unlockGroup(t) { [ ...this.xlt.querySelectorAll(`#${t}[locked="true"]`) ].forEach((e) => this.unlockShape(e)); } lockLayer(t) { [ ...this.xlt.querySelectorAll(`[layer-id="${t}"][locked="false"]`) ].forEach((e) => this.lockShape(e)); } lockGroup(t) { [ ...this.xlt.querySelectorAll(`#${t}[locked="false"]`) ].forEach((e) => this.lockShape(e)); } apiLockLayer(t) { t && this.lockLayer(t); } apiLockGroup(t) { t && this.lockGroup(t); } apiUnlockGroup(t) { t && this.unlockGroup(t); } apiUnlockLayer(t) { t && this.unlockLayer(t); } apiLoadSVG(t, { replace: i = !1, layerId: e = Math.random().toString(36).substring(2, 8), lock: r = !0, shapeClass: n = void 0, fill: u = void 0 } = {}) { const l = document.createElementNS( "http://www.w3.org/2000/svg", b.SVG ); l.innerHTML = t; const o = [...l.querySelector(b.GROUP).querySelectorAll(b.GROUP)]; return i && this.xlt.querySelectorAll(b.GROUP).forEach((f) => f.remove()), o.forEach((h) => { const f = h.firstChild; h.setAttribute("id", `g${this.getIDcount()}`), h.setAttribute("layer-id", e), h.setAttribute("locked", r), n && f.classList.add(n), u && (f.setAttribute("fill", u), f.setAttribute("fill-opacity", 1)), r || this.setElementMouseEnterLeave(h), this.xlt.appendChild(h); }), { layerId: e }; } } function _(s, t) { s.setAttributeNS( null, "points", t[0][0].toFixed(4).toString() + "," + t[0][1].toFixed(4).toString() + " " + t[0][0].toFixed(4).toString() + "," + t[0][1].toFixed(4).toString() + " " ); } d.prototype.onSvgMouseDown = function() { var i; if (this.updateMousePosition(event), this.state.svgInProgress && this.state.svgInProgress !== this.state.cursorMode) { this.state.svgInProgress !== "SHIFT" && (this.state.svgInProgress = this.state.cursorMode); return; } if (((i = this.state.currentGroup) == null ? void 0 : i.childElementCount) > 1 && this.state.cursorMode != a.TEXT) return this.clearEditElement(this.state.currentGroup), !1; const [s, t] = [this.currentMouseX, this.currentMouseY]; if (this.state.currentSVGPoints[0] = [s, t], this.state.cursorMode == a.POLYGON) if (this.state.svgInProgress == !1) { this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY]; let e = document.createElementNS("http://www.w3.org/2000/svg", "g"), r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.state.currentGroup = e, this.xlt.appendChild(e); let n = E({ tag: a.POLYLINE, attributes: this.getSVGAttributes() }); e.appendChild(n), this.state.currentElement = e.children[0], _(n, this.state.currentSVGPoints), this.state.svgInProgress = this.state.cursorMode; } else { this.updateMousePosition(event); let e = this.state.currentElement.attributes.points.value, r = this.currentMouseX.toFixed(4).toString() + "," + this.currentMouseY.toFixed(4).toString() + " "; this.state.currentElement.attributes.points.value = e.concat(r); } if (this.state.cursorMode == a.POLYLINE) if (this.state.svgInProgress == !1) { this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY]; let e = document.createElementNS("http://www.w3.org/2000/svg", "g"); this.state.currentGroup = e; let r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.xlt.appendChild(e); let n = E({ tag: a.POLYLINE, attributes: this.getSVGAttributes() }); e.appendChild(n), this.state.currentElement = e.children[0], n.setAttributeNS(null, "stroke-linecap", "round"), _(n, this.state.currentSVGPoints), this.state.svgInProgress = this.state.cursorMode; } else { this.updateMousePosition(event); let e = this.state.currentElement.attributes.points.value, r = this.currentMouseX.toFixed(4).toString() + "," + this.currentMouseY.toFixed(4).toString() + " "; this.state.currentElement.attributes.points.value = e.concat(r); } if (this.state.cursorMode == a.RECTANGLE && this.state.svgInProgress == !1) { this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY], this.state.mousePositionStart.x = this.currentMouseX, this.state.mousePositionStart.y = this.currentMouseY; let e = document.createElementNS("http://www.w3.org/2000/svg", "g"), r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.xlt.appendChild(e); let n = E({ tag: b.RECT, attributes: this.getSVGAttributes() }); e.appendChild(n), this.state.currentGroup = e, this.state.currentElement = e.children[0], n.setAttributeNS( null, "x", this.state.currentSVGPoints[0][0].toFixed(4) ), n.setAttributeNS( null, "y", this.state.currentSVGPoints[0][1].toFixed(4) ), n.setAttributeNS(null, "width", 1), n.setAttributeNS(null, "height", 1), this.state.svgInProgress = this.state.cursorMode; } if (this.state.cursorMode == a.LINE) if (this.state.svgInProgress == !1) { this.state.svgInProgress = this.state.cursorMode; const { element: e, group: r } = U({ x: s, y: t, mode: this.state.cursorMode, attributes: this.configuration }); r.setAttributeNS(null, "id", "g" + this.getIDcount().toString()), this.xlt.appendChild(r), this.state.currentElement = e, this.state.currentGroup = r; } else this.state.svgInProgress = !1, this.setElementMouseEnterLeave(this.state.currentElement); if (this.state.cursorMode == a.ARROW) if (this.state.svgInProgress == !1) { const { element: e, group: r } = U({ x: s, y: t, mode: this.state.cursorMode, attributes: this.configuration }); this.state.svgInProgress = this.state.cursorMode, r.setAttributeNS(null, "id", "g" + this.getIDcount().toString()), this.xlt.appendChild(r), this.state.currentElement = e, this.state.currentGroup = r; } else this.state.svgInProgress = !1, this.setElementMouseEnterLeave(this.state.currentElement); if (this.state.cursorMode == a.CIRCLE && this.state.svgInProgress == !1) { this.state.currentGroup != null && this.clearEditElement(this.state.currentGroup), this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY]; let e = document.createElementNS("http://www.w3.org/2000/svg", "g"), r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.xlt.appendChild(e); let n = E({ tag: b.CIRCLE, attributes: this.getSVGAttributes() }); e.appendChild(n), this.state.currentGroup = e, this.state.currentElement = e.children[0], n.setAttributeNS( null, "cx", this.state.currentSVGPoints[0][0].toFixed(4) ), n.setAttributeNS( null, "cy", this.state.currentSVGPoints[0][1].toFixed(4) ), n.setAttributeNS(null, "r", 1), this.state.svgInProgress = this.state.cursorMode; } if (this.state.cursorMode == a.ELLIPSE) if (this.state.svgInProgress == !1) { this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY]; let e = document.createElementNS("http://www.w3.org/2000/svg", "g"); this.state.currentGroup = e; let r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.xlt.appendChild(e); let n = E({ tag: a.ELLIPSE, attributes: this.getSVGAttributes() }); e.appendChild(n), this.state.currentElement = e.children[0], n.setAttributeNS( null, "cx", this.state.currentSVGPoints[0][0].toFixed(4) ), n.setAttributeNS( null, "cy", this.state.currentSVGPoints[0][1].toFixed(4) ), n.setAttributeNS(null, "rx", 1), n.setAttributeNS(null, "ry", 1), this.state.svgInProgress = this.state.cursorMode; } else this.state.svgInProgress = !1, this.setElementMouseEnterLeave(this.state.currentElement); if (this.state.cursorMode == a.DRAW) if (this.state.svgInProgress == !1) { this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY]; let e = document.createElementNS("http://www.w3.org/2000/svg", "g"); this.state.currentGroup = e; let r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.xlt.appendChild(e); let n = E({ tag: a.POLYLINE, attributes: this.getSVGAttributes() }); e.appendChild(n), this.state.currentElement = e.children[0], n.setAttributeNS( null, "points", this.state.currentSVGPoints[0][0].toFixed(4).toString() + "," + this.state.currentSVGPoints[0][1].toFixed(4).toString() + " " ), this.state.svgInProgress = this.state.cursorMode; } else this.state.svgInProgress = !1, bt(this.state.currentElement, { strokeWidth: this.configuration.strokeWidth }); if (this.state.cursorMode == a.CUBIC || this.state.cursorMode == a.QUADRATIC) if (this.state.svgInProgress == !1) { this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY]; let e = document.createElementNS("http://www.w3.org/2000/svg", "g"); this.state.currentGroup = e; let r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.xlt.appendChild(e); let n = E({ tag: b.PATH, attributes: this.getSVGAttributes() }); e.appendChild(n), this.state.currentElement = e.children[0]; let u = this.state.currentSVGPoints[0][0], l = this.state.currentSVGPoints[0][1]; n.setAttributeNS( null, "d", this.getCurvePath( u, l, u, l, u, l, u, l ) ), this.state.svgInProgress = this.state.cursorMode; } else this.state.svgInProgress = !1, this.setElementMouseEnterLeave(this.state.currentElement); if (this.state.cursorMode == a.TEXT) { let e; if (this.state.currentElement && this.finishTextGroup(), this.state.svgInProgress == !1) { this.state.currentSVGPoints[0] = [this.currentMouseX, this.currentMouseY], e = document.createElementNS("http://www.w3.org/2000/svg", "g"), this.state.currentGroup = e; let r = "g" + this.getIDcount().toString(); e.setAttributeNS(null, "id", r), e.setAttributeNS(null, "class", this.state.cursorMode), this.xlt.appendChild(e); let n; n = document.createElementNS("http://www.w3.org/2000/svg", "text"), e.appendChild(n), this.state.currentElement = e.children[0], n.setAttributeNS(null, "stroke", this.configuration.stroke), n.setAttributeNS(null, "stroke-width", "1"), n.setAttributeNS(null, "stroke-opacity", "1.0"), n.setAttributeNS( null, "x", this.state.currentSVGPoints[0][0].toFixed(4) ), n.setAttributeNS( null, "y", this.state.currentSVGPoints[0][1].toFixed(4) ), n.setAttributeNS( null, "style", "font-family: " + this.configuration.fontFamily + "; fill: " + this.configuration.stroke.toString() + ";" ), n.setAttributeNS(null, "font-size", this.configuration.fontSize), n.innerHTML = "_", this.state.svgInProgress = "text"; } } return this.state.cursorMode == a.MOVE && (this.state.svgInProgress || (this.state.svgInProgress = this.state.cursorMode)), this.state.waitElement = !1, event.preventDefault() && !1; }; function I(s, t) { return parseInt(s) + ", " + parseInt(t); } function y(s, t) { return I(s, t) + " "; } d.prototype.getSVGAttributes = function() { return { stroke: this.configuration.stroke, "stroke-width": this.configuration.strokeWidth, "stroke-opacity": this.configuration.strokeOpacity, fill: this.configuration.fill, "fill-opacity": this.configuration.fillOpacity, "stroke-linecap": this.configuration.strokeLinecap }; }; d.prototype.getCurvePath = function(s, t, i, e, r, n, u, l) { return this.state.cursorMode == a.CUBIC ? "M " + I(s, t) + " C " + y(i, e) + y(r, n) + I(u, l) : "M " + I(s, t) + " Q " + y(i, e) + I(u, l); }; function q(s) { let t = s.replace(/,/g, "").split(" "), i = 0, e = []; for (let r = 0; r < t.length; r++) x(t[r]) && (e[i] = t[r], i++); return e; } function Q(s) { return y(s[0], s[1]) + " " + y(s[2], s[3]) + " " + y(s[4], s[5]) + " " + y(s[6], s[7]); } function E({ tag: s, attributes: t }) { const i = document.createElementNS("http://www.w3.org/2000/svg", s); return Object.entries(t).forEach(([e, r]) => { i.setAttributeNS(null, e, r); }), i; } function bt(s, { strokeWidth: t }) { return s.setAttributeNS( null, "onmouseover", "this.attributes['stroke-width'].value = '" + 1.5 * t + "';" ), s.setAttributeNS( null, "onmouseout", "this.attributes['stroke-width'].value = " + t + ";" ), s; } d.prototype.mouseEnterFunction = function(s) { var r, n, u; let t = ((r = this.state.currentGroup) == null ? void 0 : r.id) || "null", i = ((n = this.state.currentElement) == null ? void 0 : n.tagName) || "null", e = ((u = this.state.currentElement) == null ? void 0 : u.parentElement.id) || "null"; m( this.configuration.debugLog, "mouseenter eventTarget=" + s.target.id + " thisGroup=" + t + " thisElement=" + i + " parent=" + e + " " + this.state.cursorMode + " " ), this.setEditElement(s.target); }; d.prototype.mouseLeaveFunction = function(s) { var r, n, u; let t = ((r = this.state.currentGroup) == null ? void 0 : r.id) || "null", i = ((n = this.state.currentElement) == null ? void 0 : n.tagName) || "null", e = ((u = this.state.currentElement) == null ? void 0 : u.parentElement.id) || "null"; m( this.configuration.debugLog, "mouseleave eventTarget=" + s.target.id + " thisGroup=" + t + " thisElement=" + i + " parent=" + e + " " + this.state.cursorMode + " " ), this.clearEditElement(s.target); }; d.prototype.removeGroupEvents = function(s) { s.removeEventListener("mouseenter", this.handleMouseEnterFunction), s.removeEventListener("mouseleave", this.handleMouseLeaveFunction), s.removeEventListener("click", this.handleMouseClickFunction); }; d.prototype.addGroupEvents = function(s) { s.addEventListener("mouseenter", this.handleMouseEnterFunction), s.addEventListener("mouseleave", this.handleMouseLeaveFunction), s.addEventListener("click", this.handleMouseClickFunction); }; d.prototype.setElementMouseEnterLeave = function(s) { return (s == null || s == null) && (s = null), this.removeGroupEvents(s), this.addGroupEvents(s), s; }; d.prototype.mouseClickFunction = function(s) { const t = s.target.parentElement; switch (this.state.cursorMode) { case a.ERASER: this.emit("erase", t), this.removeShape(t); } }; d.prototype.setEditElement = function(s) { if (ft(this.state.currentGroup, { group: s, waitElement: this.state.waitElement, svgInProgress: this.state.svgInProgress })) { m( this.configuration.debugLog, "Element conflict: " + s.attributes.class.value ); return; } if (m(this.configuration.debugLog, "setEditElement no conflict"), this.state.currentGroup == null) { let i = "thisGroup is NULL"; this.state.currentElement && (i += ", thisElement = " + this.state.currentElement.toString()), m( this.configuration.debugLog, s.attributes.class.value + " " + i ), this.state.currentGroup = s; } s.firstChild && (s.firstChild.tagName != b.PATH ? s.attributes.class ? this.state.cursorMode = s.attributes.class.value : this.state.cursorMode = s.firstChild.tagName : (this.state.cursorMode = a.CUBIC, s.firstChild.attributes.d.value.indexOf("C ") == -1 && (this.state.cursorMode = a.QUADRATIC))), this.state.svgInProgress = !1, s.childNodes.length > 1 && s.lastChild.tagName == b.GROUP && this.clearEditElement(s); const t = this.createBubbleGroup(s); s.appendChild(t), m( this.configuration.debugLog, "setEditElement " + s.id + " " + s.attributes.class.value ); }; d.prototype.clearEditElement = function(s) { var i; let t = ((i = this.state.currentGroup) == null ? void 0 : i.id) || "null"; if (m( this.configuration.debugLog, "clearEditElement: svgInProgress=" + this.state.svgInProgress + ", group=" + (s == null ? void 0 : s.id) + ", thisGroup=" + t ), this.state.svgInProgress != "SHIFT") { if (!s) { m( this.configuration.debugLog, "clearEditElement: group argument null" ); return; } if (this.state.waitElement) { m(this.configuration.debugLog, "clearEditElement: waitElement"); return; } if (this.state.currentGroup && t != s.id) { m(this.configuration.debugLog, "clearEditElement: group conflict"); return; } s.childNodes.length > 1 && (s.lastChild.tagName == a.CIRCLE || s.lastChild.tagName == "g" ? (s.lastChild.remove(), this.state.currentBubble = null, this.state.cursorMode = a.MOVE, this.state.svgInProgress = !1, this.state.currentElement = null, this.state.currentGroup = null) : s.firstChild.tagName == b.TEXT && this.state.svgInProgress == a.TEXT && this.finishTextGroup()), this.setElementMouseEnterLeave(s), this.setCursorMode(a.MOVE), this.state.svgInProgress = !1, this.state.currentElement = null, this.state.currentGroup = null; } }; function ft(s, { group: t, waitElement: i, svgInProgress: e, debugLog: r }) { if (i) return m(r, "checkElementConflict1: waitElement = " + i), !0; if (!e) return m( r, "checkElementConflict2: svgInProgress=" + e + "thisGroup=" + t.id ), !1; if (e == "SHIFT") return m( r, "checkElementConflict3: svgInProgress=" + e + "thisGroup=" + t.id ), s.id != t.id; if (e != t.firstChild.tagName) return !0; if (s != t) return m( r, "checkElementConflict5: svgInProgress=" + e + ", thisGroup=" + s.id + ", group=" + t.id + ", group element=" + t.firstChild.tagName ), !0; } d.prototype.setShiftElement = function(s) { this.state.currentGroup || (this.state.currentGroup = s.parentNode.parentNode), this.state.currentElement = this.state.currentGroup.firstChild, this.state.currentBubble = this.state.currentGroup.children[1].children.shift, this.state.cursorMode = this.state.currentElement.tagName, this.state.currentGroup.attributes.class && (this.state.cursorMode = this.state.currentGroup.attributes.class.value); let t = this.state.currentGroup.lastChild.childElementCount; for (let i = t; i > 1; i--) this.state.currentGroup.lastChild.lastChild.remove(); this.state.currentGroup.removeEventListener( "mouseenter", this.handleMouseEnterFunction ), this.state.currentGroup.removeEventListener( "mouseleave", this.handleMouseLeaveFunction ), this.state.svgInProgress = "SHIFT", m( this.configuration.debugLog, "svgInProgress = SHIFT, this.state.cursorMode = " + this.state.cursorMode ); }; d.prototype.setSizeElement = function(s, t) { const i = s.parentNode.parentNode; if (this.state.currentGroup = i, this.state.currentElement = i.firstChild, this.state.currentBubble = i.lastChild.firstChild, this.state.cursorMode = this.state.currentElement.tagName, this.state.currentElement.tagName === b.RECT && (this.state.mousePositionStart.x = this.state.currentElement.attributes.x.value, this.state.mousePositionStart.y = this.state.currentElement.attributes.y.value), this.state.cursorMode === a.CIRCLE || this.state.cursorMode === a.ELLIPSE) { const e = i.lastChild.childElementCount; for (let r = e; r > 0; r--) i.lastChild.lastChild.remove(); } this.state.svgInProgress = "SIZE", m( this.configuration.debugLog, "svgInProgress = SIZE, this.state.cursorMode = " + this.state.cursorMode + " " + this.state.currentElement.tagName ), i.removeEventListener("mouseenter", this.handleMouseEnterFunction), i.removeEventListener("mouseleave", this.handleMouseLeaveFunction); }; d.prototype.setPointElement = function(s) { const t = s.parentNode.parentNode; this.state.currentBubble = s, this.state.currentGroup = t, this.state.currentElement = t.firstChild, parseInt(s.id) == s.parentNode.childElementCount - 1 && (this.state.currentBubble = s), s.parentNode.lastChild.tagName == b.GROUP && s.parentNode.lastChild.remove(), this.state.currentGroup.attributes.class ? this.state.cursorMode = this.state.currentGroup.attributes.class.value : this.state.cursorMode = this.state.currentElement.tagName, t.removeEventListener("mouseenter", this.handleMouseEnterFunction), t.removeEventListener("mouseleave", this.handleMouseLeaveFunction), this.state.svgInProgress = "POINT"; }; d.prototype.setNewPointElement = function(s) { const t = s.parentNode.parentNode.parentNode; this.state.currentBubble = s, this.state.currentGroup = t, this.state.currentElement = t.firstChild, parseInt(s.id) == s.parentNode.childElementCount - 1 && (this.state.currentBubble = s), this.state.cursorMode = this.state.currentElement.tagName, t.removeEventListener("mouseenter", this.handleMouseEnterFunction), t.removeEventListener("mouseleave", this.handleMouseLeaveFunction), this.state.currentElement.attributes.points.value = mt( this.state.currentElement, this.state.currentBubble ), this.state.currentBubble.id = (parseInt(this.state.currentBubble.id) + 1).toString(), this.state.svgInProgress = "NEW"; }; function mt(s, t) { const { cx: i, cy: e } = t.attributes, r = parseInt(t.id), n = i.value + "," + e.value, u = s.attributes.points.value.trim().split(" "); let l = ""; for (let p = 0; p < u.length; p++) l += u[p] + " ", p == r && (l += n + " "); return l; } d.prototype.createBubbleForCircle = function(s, { cx: t, cy: i, r: e }) { return s.setAttributeNS(null, "class", "bubbles"), s.appendChild(this.createShiftBubble(t, i, "shift")), s.appendChild(this.createSizeBubble(e + t, i, "E")), s.appendChild(this.createSizeBubble(t, e + i, "S")), s.appendChild(this.createSizeBubble(t - e, i, "W")), s.appendChild(this.createSizeBubble(t, i - e, "N")), s; }; d.prototype.createBubbleForEllipse = function(s, { cx: t, cy: i, rx: e, ry: r }) { return s.appendChild(this.createShiftBubble(t, i, "shift")), s.appendChild( this.createSizeBubble(t + e * 0.707, i + r * 0.707, "SE") ), s.appendChild( this.createSizeBubble(t + e * 0.707, i - r * 0.707, "NE") ), s.appendChild( this.createSizeBubble(t - e * 0.707, i - r * 0.707, "NW") ), s.appendChild( this.createSizeBubble(t - e * 0.707, i + r * 0.707, "SW") ), s; }; d.prototype.createBubbleForRectangle = function(s, { x: t, y: i, width: e, height: r }) { return s.appendChild(this.createShiftBubble(t, i, "shift")), s.appendChild(this.createSizeBubble(t + e, i + r)), s; }; d.prototype.createBubbleForLine = function(s, { x1: t, y1: i, x2: e, y2: r }) { return s.appendChild( this.createShiftBubble((e + t) / 2, (r + i) / 2, "shift") ), s.appendChild(this.createPointBubble(t, i, "x1-y1")), s.appendChild(this.createPointBubble(e, r, "x2-y2")), s; }; d.prototype.createBubbleForPath = function(s, t) { let i = t.attributes.d.value, e = i.indexOf("Q ") > 0, r = q(i); e && (r[6] = r[4], r[7] = r[5], r[4] = r[2], r[5] = r[3]); let n, u; return e ? (n = parseFloat(r[0]) + parseFloat(r[2]) + parseFloat(r[6]), u = parseFloat(r[1]) + parseFloat(r[3]) + parseFloat(r[7]), n = (n / 3).toFixed(4), u = (u / 3).toFixed(4)) : (n = parseFloat(r[0]) + parseFloat(r[2]) + parseFloat(r[4]) + parseFloat(r[6]), u = parseFloat(r[1]) + parseFloat(r[3]) + parseFloat(r[5]) + parseFloat(r[7]), n = (n / 4).toFixed(4), u = (u / 4).toFixed(4)), s.appendChild( gt({ coords: r, attributes: this.getSVGAttributes() }) ), s.appendChild(this.createShiftBubble(n, u, "shift")), s.appendChild( W({ x1: r[0], y1: r[1], x2: r[2], y2: r[3], id: "l1", attributes: this.getSVGAttributes() }) ), s.appendChild( W({ x1: r[4], y1: r[5], x2: r[6], y2: r[7], id: "l2", attributes: this.getSVGAttributes() }) ), s.appendChild( this.createCurveBubble(r[0], r[1], "p1") ), s.appendChild( this.createCurveBubble(r[6], r[7], "p2") ), s.appendChild( this.createCurveBubble(r[2], r[3], "c1") ), e || s.appendChild( this.createCurveBubble(r[4], r[5], "c2") ), s; }; d.prototype.createBubbleForPolyline = function(s, t) { const e = t.attributes.points.value.trim().split(" "), r = e[0].split(","); let n = parseFloat(r[0]), u = parseFloat(r[1]), l, p, o = 0, h = 0, f; for (let c = 0; c < e.length; c++) o += n, h += u, c < e.length - 1 && (f = e[c + 1].split(","), l = parseFloat(f[0]), p = parseFloat(f[1]), n = l, u = p); n = o / e.length, u = h / e.length, s.appendChild(this.createShiftBubble(n, u, "shift")); const g = document.createElementNS( "http://www.w3.org/2000/svg", b.GROUP ); n = parseFloat(r[0]), u = parseFloat(r[1]); for (let c = 0; c < e.length; c++) s.appendChild(this.createPointBubble(n, u, c.toString())), c < e.length - 1 && (f = e[c + 1].split(","), l = parseFloat(f[0]), p = parseFloat(f[1]), g.appendChild( this.createNewPointBubble( 0.5 * (n + l), 0.5 * (u + p), c.toString() + ".5" ) ), n = l, u = p); if (t.tagName == a.POLYGON) { const [c, M] = e[0].split(","), F = (e.length - 1).toString() + ".5"; n = parseFloat(c), u = parseFloat(M), g.appendChild( this.createNewPointBubble(0.5 * (n + l), 0.5 * (u + p), F) ); } return s.appendChild(g), s; }; d.prototype.createBubbleForText = function(s, { x: t, y: i }) { return s.appendChild(this.createShiftBubble(t, i, "shift")), s; }; d.prototype.createBubbleGroup = function(s) { s || m( this.configuration.debugLog, "group arg null, thisGroup=" + this.state.currentGroup ); const t = s.firstChild, i = dt(t.tagName), e = document.createElementNS( "http://www.w3.org/2000/svg", b.GROUP ); if (e.classList.add("bubbles"), t.tagName !== b.PATH) for (let r in i) i[r] = Et(t, r); switch (t.tagName) { case b.CIRCLE: return this.createBubbleForCircle(e, i); case b.ELLIPSE: return this.createBubbleForEllipse(e, i); case b.RECT: return this.createBubbleForRectangle(e, i); case b.LINE: return this.createBubbleForLine(e, i); case b.PATH: return this.createBubbleForPath(e, t); case a.POLYGON: case a.POLYLINE: return this.createBubbleForPolyline(e, t); case b.TEXT: return this.createBubbleForText(e, i); } }; d.prototype.createShiftBubble = function(s, t, i) { const e = this.createBubbleStub(s, t); return e.setAttributeNS(null, "r", this.state.bubbleRadius * 1.25), e.setAttributeNS(null, "stroke", "#004477"), e.setAttributeNS(null, "fill-opacity", "1.0"), e.addEventListener("mousedown", () => { this.setShiftElement(e); }), e.addEventListener("mouseup", () => { this.setElementMouseEnterLeave(e); }), e.setAttributeNS(null, "style", "cursor:move;"), e.setAttributeNS(null, "id", i), e; }; d.prototype.createSizeBubble = function(s, t, i) { let e = this.createBubbleStub(s, t); return e.setAttributeNS(null, "fill-opacity", "0.6"), e.addEventListener("mousedown", (r) => { this.setSizeElement(e, r); }), e.setAttributeNS(null, "id", i), e; }; d.prototype.createPointBubble = function(s, t, i) { const e = this.createBubbleStub(s, t); return e.setAttributeNS(null, "fill-opacity", "0.6"), e.setAttributeNS(null, "id", i), e.addEventListener("mousedown", () => { this.setPointElement(e); }), e; }; d.prototype.createNewPointBubble = function(s, t, i) { const e = this.createBubbleStub(s, t); return e.setAttributeNS(null, "r", this.state.bubbleRadius * 0.8), e.setAttributeNS(null, "stroke", "#555555"), e.setAttributeNS(null, "stroke-opacity", "0.6"), e.setAttributeNS(null, "fill-opacity", "0.4"), e.addEventListener("mousedown", () => { this.setNewPointElement(e); }), e.setAttributeNS(null, "id", i), e; }; d.prototype.createCurveBubble = function(s, t, i) { const e = this.createBubbleStub(s, t); return e.setAttributeNS(null, "stroke", "#333333"), e.setAttributeNS(null, "stroke-opacity", "0.6"), e.setAttributeNS(null, "fill-opacity", "0.8"), e.addEventListener("mousedown", () => { this.setPointElement(e); }), e.setAttributeNS(null, "id", i), e; }; function W({ x1: s, y1: t, x2: i, y2: e, id: r, attributes: n }) { const u = E({ tag: a.LINE, attributes: n }); return u.setAttributeNS(null, "x1", s), u.setAttributeNS(null, "y1", t), u.setAttributeNS(null, "x2", i), u.setAttributeNS(null, "y2", e), u.setAttributeNS(null, "id", r), u.setAttributeNS(null, "stroke-width", "1"), u; } function gt({ coords: s, attributes: t }) { const i = E({ tag: a.POLYLINE, attributes: t }); return i.setAttributeNS(null, "id", "poly"), i.setAttributeNS(null, "points", Q(s)), i.setAttributeNS(null, "stroke-opacity", "0.0"), i; } d.prototype.createBubbleStub = function(s, t) { const i = E({ tag: a.CIRCLE, attributes: this.getSVGAttributes() }); return isNaN(s) && alert("offsetX: " + s.toString()), isNaN(t) && alert("offsetY: " + t.toString()), i.setAttributeNS(null, "cx", s), i.setAttributeNS(null, "cy", t), i.setAttributeNS(null, "r", this.state.bubbleRadius), i.setAttributeNS(null, "fill", "#FFFFFF"), i.setAttributeNS(null, "stroke", "#222222"), i.setAttributeNS(null, "stroke-width", this.state.bubbleRadius * 0.25), i; }; function Et(s, t) { return parseFloat(parseFloat(s.attributes[t].value).toFixed(1)); } function x(s) { return !isNaN(parseFloat(s)) && isFinite(s); } d.prototype.onSvgMouseMove = function(s) { return this.renderFunction(s), s.preventDefault(), !1; }; function vt(s, t, i, e) { return Math.sqrt(Math.pow(s - i, 2) + Math.pow(t - e, 2)); } d.prototype._getMousePosition = function(s) { const t = this.containerElement.getBoundingClientRect(); return { x: s.clientX - t.left, y: s.clientY - t.top }; }; d.prototype.updateMousePosition = function(s) { const t = this.touchSupported ? s.originalEvent.touches[0] : s; this.state.mousePosition = this._getMousePosition(t); }; d.prototype.updateSvgByElement = function(s) { if (this.state.cursorMode != a.MOVE) { if (this.state.cursorMode === a.POLYGON || this.state.cursorMode === a.POLYLINE && this.state.svgInProgress === a.POLYGON) { if (this.state.svgInProgress == !1) return; if (this.updateMousePosition(s), this.state.svgInProgress == "SHIFT") { let t = this.state.currentElement.attributes.points.value.trim(), i = t.split(" "); if (this.state.currentBubble != null) { let e = parseFloat(this.state.currentBubble.attributes.cx.value), r = parseFloat(this.state.currentBubble.attributes.cy.value), n = this.currentMouse