{"version":3,"sources":["https://lively-kernel.org/lively4/lively4-leo/src/components/widgets/lively-drawboard.js"],"names":["Morph","ContextMenu","CommandHistory","paper","pt","_","debouncedObjects","WeakMap","debounceMember","that","func","args","has","set","Map","debouncedObject","get","clearTimeout","clearId","setTimeout","LivelyDrawboard","initSVGInteraction","lively","addEventListener","svg","e","onPointerDown","onPointerUp","isWindow","parentElement","isMinimized","getOffset","obj","bounds","getBoundingClientRect","left","top","color","getAttribute","value","setAttribute","penSize","background","style","backgroundColor","querySelector","_paper","setup","document","createElement","initialize","resetWindowTitle","lastPath","Object","createElementNS","id","appendChild","evt","onContextMenu","onExtentChanged","onFocus","onBlur","onBackgroundColor","detail","onPenColor","onPenSize","draggable","onDragStart","onDrag","onDragEnd","updateCanvasExtent","observeHTMLChanges","strokes","registerButtons","target","attachedCallback","fixedControls","hidden","offsetY","offsetX","width","height","setPosition","mutationObserver","disconnect","MutationObserver","mutations","observer","forEach","record","observe","childList","subtree","characterData","attributes","freehand","classList","add","overflow","isFocused","activeElement","focus","pointerType","button","ctrlKey","visible","stopPropagation","preventDefault","pointerId","offset","path","altKey","command","points","eventPos","screenOffset","subPt","clientX","clientY","pos","push","renderPath","onPointerMove","length","first","rest","x","y","map","ea","join","lastPointerUp","Date","now","addPt","removeEventListener","paperPath","Path","Array","from","querySelectorAll","filter","eaPath","intersects","type","stroke","container","execute","remove","unexecute","addChild","addCommand","simplifyPath","project","activeLayer","removeChildren","importSVG","getItems","class","simplify","paperSVG","exportSVG","paperSVGPath","clear","innerHTML","undoStroke","undo","redoStroke","redo","onUndoStroke","onRedoStroke","shiftKey","menu","openIn","body","size","onClose","confirm","getScreenScale","window","innerWidth","outerWidth","scale","dragOffset","getPosition","dataTransfer","setDragImage","onLoadFile","fileName","prompt","s","fetch","svgString","text","div","firstChild","setAutosaveTarget","autosaveTo","windowTitle","onActivateSave","undefined","saveSVG","urlString","getExtent","outerHTML","URL","files","saveFile","notify","err","livelyExample","livelyMigrate","other"],"mappings":"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","file":"lively-drawboard.js","sourcesContent":["/*MD # Drawboad \n\n![](lively-drawboard.png){width=400px}\n\nMD*/\n\n\nimport Morph from 'src/components/widgets/lively-morph.js';\nimport ContextMenu from 'src/client/contextmenu.js';\nimport CommandHistory  from \"src/client/command-history.js\";\nimport paper from \"src/external/paperjs/paper-core.js\";\nimport {pt} from \"src/client/graphics.js\";\n\nimport _ from 'src/external/lodash/lodash.js'\n\nconst debouncedObjects = new WeakMap();\nfunction debounceMember(that, func, ...args) {\n  if(!debouncedObjects.has(that)) {\n    debouncedObjects.set(that, new Map());\n  }\n  let debouncedObject = debouncedObjects.get(that);\n  if(debouncedObject.has(func)) {\n    clearTimeout(debouncedObject.get(func));\n  }\n  \n  let clearId = setTimeout(() => {\n    that[func](...args);\n  }, 1000);\n  debouncedObject.set(func, clearId);\n}\n\nexport default class LivelyDrawboard extends Morph {\n  \n  initSVGInteraction() {\n    lively.addEventListener(\"drawboard\", this.svg, \"pointerdown\", \n      (e) => this.onPointerDown(e));\n    lively.addEventListener(\"drawboard\", this.svg, \"pointerup\", \n      (e) => this.onPointerUp(e));\n  }\n  \n  // Lively Window API\n  get isWindow() {\n    return this.parentElement && !this.parentElement.isWindow\n  }\n  \n  isMinimized() {\n    return false\n  }\n  \n  getOffset(obj) {\n    var bounds = obj.getBoundingClientRect()\n    return  pt(bounds.left, bounds.top)\n  } \n  \n  get color() {\n    return this.getAttribute(\"color\")\n  }\n  \n  set color(value) {\n    this.setAttribute(\"color\", value)\n  }\n  \n  get penSize() {\n    return this.getAttribute(\"pen-size\")\n  }\n  \n  set penSize(value) {\n    this.setAttribute(\"pen-size\", value)\n  }\n  \n  get background() {\n    return this.style.backgroundColor\n  }\n  \n  set background(value) {\n    this.style.backgroundColor = value\n  }\n  \n\n  get svg() {\n    return this.querySelector(\"#svg\");\n  }\n  \n  get paper() {\n    if (!this._paper) {\n      paper.setup(document.createElement(\"canvas\"));\n      this._paper = paper;\n    }\n    return this._paper;\n  }\n  \n  initialize() {\n    this.resetWindowTitle();\n\n    this.lastPath = new Object();\n\n    var svg = this.get(\"#svg\");\n    if (!svg) {\n      svg =  document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n      svg.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n      svg.id = \"svg\";\n      svg.style = `position: absolute;\n        top: 0px;\n        left: 0px;\n        width: 100%;\n        height: 100%;\n        border: none;\n        opacity: 1;\n        touch-action: none;`;\n      this.appendChild(svg);\n    }\n    \n    svg.setAttribute(\"data-is-meta\", true);\n    \n    // we cannot disable the events here, because we need them for drawing\n    // the downside is, that the SVG element shows up in the Halo\n    // svg.style.pointerEvents = \"none\"\n    \n    \n    this.addEventListener('contextmenu',  evt => this.onContextMenu(evt), false);\n\n    this.initSVGInteraction();\n    lively.addEventListener(\"drawboard\", this, \"extent-changed\", \n      e => this.onExtentChanged(e));\n    lively.addEventListener(\"drawboard\", this, \"focus\", \n      e => this.onFocus(e));\n    lively.addEventListener(\"drawboard\", this, \"blur\", \n      e => this.onBlur(e));\n    lively.addEventListener(\"drawboard\", this.get('#backgroundColor'), \"value-changed\", \n      e => this.onBackgroundColor(e.detail.value));  \n    lively.addEventListener(\"drawboard\", this.get('#penColor'), \"value-changed\", \n      e => this.onPenColor(e.detail.value));  \n    lively.addEventListener(\"drawboard\", this.get('#penSize'), \"value-changed\", \n      e => this.onPenSize(e.detail.value));  \n\n    \n    this.get('#controls').draggable = true\n    lively.addEventListener(\"drawboard\", this.get('#controls'), \"dragstart\", \n      e => this.onDragStart(e));  \n    lively.addEventListener(\"dragboard\", this.get('#controls'), \"drag\", \n      e => this.onDrag(e));  \n    lively.addEventListener(\"dragboard\", this.get('#controls'), \"dragend\", \n      e => this.onDragEnd(e));  \n\n    this.color = \"black\";\n    \n    this.updateCanvasExtent();\n    this.observeHTMLChanges();\n   \n    this.get(\"#backgroundColor\").value = this.background;\n    this.get(\"#penColor\").value = this.color;\n    this.get(\"#penSize\").value = this.penSize;\n   \n    this.strokes = new CommandHistory();\n    this.registerButtons();\n    \n    this.get(\"lively-resizer\").target = this; // shadow root cannot look outside\n    \n    this.setAttribute(\"tabindex\", 0);\n  }\n  \n  attachedCallback() {\n    if (this.parentElement.isWindow) {\n      this.fixedControls = true;\n      this.get(\"#controls\").hidden = false ;\n      this.get(\"lively-resizer\").hidden = true;\n    } else {\n      this.get('#controls').draggable = false;\n      this.fixedControls = false;\n      this.get(\"lively-resizer\").hidden = false;\n    }\n    setTimeout(() => this.updateCanvasExtent(), 1000);\n  }\n  \n  onExtentChanged() {\n    this.updateCanvasExtent();\n  }\n  \n  updateCanvasExtent() {\n    var offsetY = 0;\n    var offsetX = 0;\n    if (this.fixedControls) {\n      offsetY = 30\n      this.get(\"#controls\").style.top = \"0px\"\n    } else {\n      this.get(\"#controls\").style.top = \"-28px\"\n    }\n    \n    var bounds = this.getBoundingClientRect()\n    var width = (bounds.width - offsetX) + \"px\"\n    var height = (bounds.height - offsetY) + \"px\"\n    if (this.svg) {\n      lively.setPosition(this.svg, pt(offsetX, offsetY))\n      this.svg.style.width = width\n      this.svg.style.height = height\n    }\n  }\n  \n  observeHTMLChanges() {\n    if (this.mutationObserver) this.mutationObserver.disconnect()\n    this.mutationObserver = new MutationObserver((mutations, observer) => {\n        mutations.forEach(record => {\n          if (record.target == this) {\n            this.onExtentChanged()\n          }\n        })\n    });\n    this.mutationObserver.observe(this, {\n      childList: false, \n      subtree: false, \n      characterData: false, \n      attributes: true});\n  }\n\n  freehand() {\n    this.classList.add(\"freehand\")\n    this.get(\"#svg\").style.overflow = \"visible\";\n    \n    // this.style.backgroundColor = \"transparent\"\n    // this.style.border = \"0pxffffff\"        \n    // this.get(\"svg\").style.overflow = \"visible\"\n  }\n    \n  onPointerDown(evt) {\n    if (!this.svg) return\n    \n    var isFocused = document.activeElement == this\n    if (!isFocused) {\n      this.style['z-index'] = 200\n      // evt.preventDefault()\n      \n      this.focus()\n      // return \n    }\n    \n    if (evt.pointerType == \"touch\") {\n      // console.log(\"ignor touch events for drawing...\")\n      return\n    }\n\n    if ((evt.pointerType == \"mouse\" && evt.button == 2) \n        || evt.ctrlKey\n        || ContextMenu.visible()) {\n      // context menu\n      return;\n    }\n    \n    evt.stopPropagation();\n    evt.preventDefault();\n    \n    var id = evt.pointerId;   \n   \n    this.offset  = this.getOffset(this.svg);\n    var path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n    path.setAttribute(\"stroke\", this.color);\n    path.setAttribute(\"stroke-width\", 2);        \n    path.setAttribute(\"fill\", \"none\");        \n    this.get(\"#svg\").appendChild(path)\n    \n    if ((evt.pointerType == \"pen\" && evt.button == 2)\n      || evt.altKey ) {\n      path.command = \"delete\";\n      path.setAttribute(\"stroke\", \"red\");\n      path.setAttribute(\"stroke-width\", 4);        \n    } else {\n      path.setAttribute(\"stroke\", this.color);\n      path.setAttribute(\"stroke-width\", this.penSize);        \n    }\n    \n    \n    this.lastPath[id] = path;\n    path.points = []\n    var eventPos = this.eventPos(evt)\n    this.screenOffset = this.eventPos(evt).subPt( pt(evt.clientX, evt.clientY))\n\n    // use screenX and screenY for higher resolution\n    var pos = eventPos.subPt(this.offset).subPt(this.screenOffset)\n\n    path.points.push(pos)\n    this.renderPath(path)\n    \n    lively.addEventListener(\"drawboard\", this, \"pointermove\", (e) => this.onPointerMove(e), false);\n    \n    // this.setPointerCapture(evt.pointerId);\n  }  \n  \n  renderPath(path) {\n    if (!path.points || path.points.length == 0) return \n    // console.log(\"render \" + path.points)\n    var first, rest;\n    [first, ...rest]= path.points\n    path.setAttribute(\"d\", \"M \"+ first.x +\" \" + first.y + \n      rest.map(ea => \"L \" + ea.x + \" \"+ ea.y).join(\" \"))\n  }\n  \n  // Event handler called for each pointerdown event:\n  onPointerMove(evt) {\n    \n    // #BUG seems to jump back...\n    // if (evt.getCoalescedEvents) {\n    //   var i=1\n    //   var missedEvents = evt.getCoalescedEvents()\n    //   // lively.showPath(missedEvents.map( ea => pt(ea.clientX, ea.clientY)))\n    //   missedEvents.forEach(ea => {\n    //     lively.showPoint(lively.getPosition(evt), 10000).innerHTML = \"\" + i++      \n    //     this.onPointerMove(ea)\n    //   })\n    // }\n    \n    // console.log(\"move \" + (Date.now() - this.lastMove))\n    // this.lastMove = Date.now()\n    \n    // DEBUG\n    // window.eventRecorder = []\n    // window.eventRecorder && window.eventRecorder.push(evt)\n    var id = evt.pointerId;   \n    var path = this.lastPath[id];\n    \n    if (!path) return\n    \n    var eventPos = this.eventPos(evt)\n    var pos = eventPos.subPt(this.offset).subPt(this.screenOffset)\n\n    path.points.push(pos)\n    this.renderPath(path)\n\n  }\n\n  onPointerUp(evt) {\n    // this.releasePointerCapture(evt.pointerId)\n    \n    \n    var id = evt.pointerId;\n    var path = this.lastPath[id];\n    if (!path) return;\n    this.lastPointerUp  = Date.now()\n\n    \n    if (path.points.length ==  1) {\n     var pos = this.eventPos(evt).subPt(this.offset).subPt(this.screenOffset)\n     // ensure a visible stroke if no pointer was not moved\n     path.points.push(pos.addPt(pt(1,1)))\n    }\n\n    this.renderPath(path)\n\n    // lively.notify(\"strokes: \" + path.points.length )\n    \n    // path.setAttribute(\"d\", path.getAttribute(\"d\") + \n    //   path.points.map( ea => \" L \"+ ea.x +\" \" + ea.y ).join(\"\"))\n\n    lively.removeEventListener(\"drawboard\", this, \"pointermove\")    \n\n\n    delete this.lastPath[id];\n    \n    var paperPath =  new this.paper.Path(path.getAttribute(\"d\"))\n    \n    if (path.command == \"delete\") {\n        Array.from(this.get(\"#svg\").querySelectorAll(\"path\"))\n          .filter( ea => {\n            var eaPath = new paper.Path(ea.getAttribute(\"d\"))\n          \n            try { \n              return eaPath.intersects(paperPath);  \n            } catch(e) { return false}\n          })\n          .forEach( ea => {\n            var command = {\n              type: \"delete\",\n              stroke: ea,\n              container: this.get(\"#svg\"),\n              execute: function(){\n                this.stroke.remove();\n              },\n              unexecute: function(){\n                this.container.addChild(this.stroke);\n              }\n            };\n            this.strokes.addCommand(command);\n            command.execute();\n          });\n        path.remove();\n    } else {\n      this.simplifyPath(path)\n      this.get(\"#svg\").appendChild(path)\n\n      var command = {\n        type: \"stroke\",\n        stroke: path,\n        container: this.get(\"#svg\"),\n        execute: function() {\n          this.container.appendChild(this.stroke);\n        },\n        unexecute: function(){\n          this.stroke.remove();\n        }\n      }\n      this.strokes.addCommand(command)\n    }\n    debounceMember(this, \"saveSVG\");\n  }\n  \n  simplifyPath(path) {\n    // if (true) {\n    //   var tmp = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\")\n    //   tmp.innerHTML = path.outerHTML\n    //   var debugPath = tmp.querySelector(\"path\")\n    //   debugPath.setAttribute(\"stroke\", \"red\")\n    //   path.parentElement.appendChild(debugPath)            \n    // }\n    \n    this.paper.project.activeLayer.removeChildren();\n    this.paper.project.importSVG(path)\n    var paperPath = paper.project.getItems({class: paper.Path})[0]\n    paperPath.simplify(3)\n    var paperSVG = paper.project.exportSVG()\n    var paperSVGPath = paperSVG.querySelector(\"path\")\n    path.setAttribute(\"d\", paperSVGPath.getAttribute(\"d\"))\n  }\n  \n\n  clear() {\n    this.get(\"#svg\").innerHTML = \"\"\n  }\n  \n  undoStroke() {\n    this.strokes.undo();\n  }\n\n  redoStroke() {\n    this.strokes.redo();\n  }\n  \n  onUndoStroke() {\n    this.undoStroke();\n  }\n  \n  onRedoStroke() {\n    this.redoStroke();\n  }\n  \n  onContextMenu(evt) {\n      if (this.lastPointerUp && (Date.now() - this.lastPointerUp < 1000)) {\n        evt.stopPropagation();\n        evt.preventDefault();\n        return; // #HACK custom prevent default....\n      }\n      \n      if (!evt.shiftKey) {\n        evt.stopPropagation();\n        evt.preventDefault();\n\n        var menu = new ContextMenu(this, [\n              [\"clear\", () => this.clear()],\n              [\"undo stroke\", () => this.undoStroke()],\n              [\"redo stroke\", () => this.redoStroke()],\n            ]);\n        menu.openIn(document.body, evt, this);\n        return true;\n      }\n\n  }\n  \n  onFocus() {\n    if (!this.fixedControls)\n      this.get(\"#controls\").hidden = false\n  }\n  \n  onBlur() {\n    if (!this.fixedControls)\n      this.get(\"#controls\").hidden = true\n  }\n  \n  onBackgroundColor(color) {\n    this.style.backgroundColor = color\n  }\n  \n  onPenColor(color) {\n    this.color = color\n  }\n  \n  onPenSize(size) {\n    this.penSize = size\n  }\n  \n  async onClose() {\n    if (await lively.confirm(\"Remove drawing?\")) {\n      this.remove()\n    }\n  }\n  \n  /*\n    // 100% NoPinch\n    window.outerWidth // 1440\n    window.innerWidth  // 1440\n    document.documentElement.clientWidth // 1440\n    \n    // 100% MaxPinch\n    window.outerWidth // 1440\n    window.innerWidth // 360\n    document.documentElement.clientWidth // 1440\n    \n    // 200% NoPinch\n    window.outerWidth // 1440 \n    window.innerWidth // 720\n    document.documentElement.clientWidth // 712\n  */\n  getScreenScale() {\n    return window.innerWidth / window.outerWidth;\n  }\n  \n  eventPos(evt) {\n    // return pt(evt.clientX, evt.clientY)\n    \n    var scale = this.getScreenScale()\n    \n    // return pt(evt.pageX * scale, evt.pageY * scale)\n    return pt(evt.clientX, evt.clientY)\n    // #HACK for subpixel precision\n    /// return pt(evt.screenX * scale, evt.screenY * scale)\n  }\n  \n  onDragStart(evt){ \n    if (this.fixedControls) return\n    this.dragOffset = lively.getPosition(this).subPt( pt(evt.clientX, evt.clientY))\n\n    evt.dataTransfer.setDragImage(document.createElement(\"div\"), 0, 0); \n    evt.stopPropagation(); \n  }\n  \n  onDrag(evt) {\n    if (this.fixedControls) return\n\n    if (evt.clientX == 0) return // #Issue bug in browser? Ignore garbage event\n    \n    var pos =  pt(evt.clientX, evt.clientY)\n    // console.log(\"drag \" + pos.x)\n    \n        // DEBUG\n    // window.eventRecorder = []\n    // window.eventRecorder && window.eventRecorder.push(evt)\n\n    \n    \n    lively.setPosition(this, pos.addPt(this.dragOffset))\n  }\n  \n  onDragEnd() {\n    if (this.fixedControls) return\n    \n  }\n\n  async onLoadFile() {\n    let fileName = await lively.prompt('Load the following file:', 'https://lively4/dropbox/_test.svg');\n    if(!fileName) { return; }\n\n    this.svg && this.svg.remove();\n    \n    let s = await fetch(fileName);\n    let svgString = await s.text();\n    \n    // svgString to html element\n    let div = document.createElement('div');\n    div.innerHTML = svgString;\n    this.appendChild(div.firstChild);\n    \n    this.initSVGInteraction();\n    this.setAutosaveTarget(fileName);\n    this.strokes.clear();\n  }\n  \n  setAutosaveTarget(fileName) {\n    this.autosaveTo = fileName;\n\n    this.resetWindowTitle();\n    this.windowTitle += \": \" + fileName;\n  }\n  \n  resetWindowTitle() {\n    this.windowTitle = \"Draw Board\";\n  }\n  \n  async onActivateSave() {\n    let fileName = await lively.prompt('Choose file to sync with:', 'https://lively4/dropbox/_test.svg');\n    this.autosaveTo = undefined;\n    this.resetWindowTitle();\n    \n    if(fileName) {\n      this.setAutosaveTarget(fileName);\n      this.saveSVG();\n    }\n  }\n  \n  async saveSVG() {\n    let urlString = this.autosaveTo;\n\n    if(!urlString || urlString === '') { return; }\n    \n    this.get('#svg').setAttribute(\"width\", lively.getExtent(this).x)\n    this.get('#svg').setAttribute(\"height\", lively.getExtent(this).y)\n    \n    let svg = this.get('#svg').outerHTML;\n    \n    try {\n      new URL(urlString);\n      await lively.files.saveFile(urlString, svg);\n      lively.notify(\"saved drawboard\", urlString);\n    } catch(err) {\n      lively.notify(err);\n    }\n  }\n\n  livelyExample() {\n     this.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" id=\"svg\" data-is-meta=\"true\" style=\"position: absolute; top: 30px; left: 0px; width: 650px; height: 350.807px; border: none; opacity: 1; touch-action: none;\"><path stroke=\"rgb(255,142,0)\" stroke-width=\"2\" fill=\"none\" d=\"M146,47.80682c-19.32721,0 -28.34628,7.00971 -43,18c-10.8015,8.10113 -18.41714,16.15086 -25,28c-10.29464,18.53035 -18.67394,41.95635 -15,64c1.2894,7.73639 10.373,14.746 14,22c7.6676,15.33519 14.53424,30.76162 23,46c31.56566,56.81819 121.97168,69.56227 179,65c5.06981,-0.40558 21.98473,-3.0375 27,-5c4.08832,-1.59978 20.94649,-13.42967 23,-15c29.61184,-22.64435 10.93081,-61.34595 5,-91c-2.98498,-14.92491 -1.964,-28.92801 -9,-43c-2.07446,-4.14893 -4.43785,-4.41299 -7,-8c-10.93404,-15.30765 -17.56364,-22.42273 -33,-34c-7.47776,-5.60832 -13.18705,-13.09352 -21,-17c-3.28654,-1.64327 -11.44268,-2.40711 -15,-3c-2.19593,-0.36599 -3.50121,-2.87591 -5,-4c-4.9657,-3.72427 -14.39235,-1.13078 -20,-3c-1.94657,-0.64886 -1.02322,-3.25581 -4,-4c-9.08588,-2.27147 -16.7621,-3.15242 -26,-5c-3.30657,-0.66131 -4.03294,-3.01098 -7,-4c-5.66079,-1.88693 -11.28596,-2.04766 -17,-3c-1.64399,-0.274 -2.82149,-1.82149 -4,-3c-3.10012,-3.10012 -14.47683,-3 -19,-3\"></path><path stroke=\"rgb(255,142,0)\" stroke-width=\"2\" fill=\"none\" d=\"M125,107.80682c-1.05088,0 -5.3369,-0.6631 -6,0c-1.20644,1.20644 -0.48308,18.3559 0,19c6.23341,8.31121 17.47112,34.61155 34,28c3.11115,-1.24446 4.53133,-6.42983 6,-9c1.28479,-2.24838 14.10284,-25.89716 10,-30c-2.0199,-2.0199 -3.75818,-7.75818 -7,-11c-3.79356,-3.79356 -20.82568,-5.58716 -26,-3c-1.79343,0.89671 -1.78126,2.78126 -3,4\"></path><path stroke=\"rgb(255,142,0)\" stroke-width=\"2\" fill=\"none\" d=\"M226,109.80682c-4.1372,4.1372 -11.28308,7.13231 -13,14c-1.5695,6.278 -0.08992,25.91008 3,29c4.51687,4.51687 24.02083,4 31,4c1.03326,0 8.68465,0.6307 9,0c1.80814,-3.61628 0,-12.98538 0,-17c0,-38.59747 -15.61932,-44.39448 -52,-34\"></path><path stroke=\"rgb(255,142,0)\" stroke-width=\"2\" fill=\"none\" d=\"M151,214.80682c0,6.02818 2.08588,14.27147 9,16c0.98765,0.24691 4.35185,-0.37037 5,0c1.63717,0.93553 2.52758,2.82206 4,4c0.80899,0.64719 24.04656,0 27,0c6.32993,0 14.34507,1.39296 20,-2c7.95421,-4.77253 13.32877,-6.49315 19,-15c2.70716,-4.06074 7,-14.50934 7,-12\"></path><path stroke=\"rgb(255,142,0)\" stroke-width=\"2\" fill=\"none\" d=\"M137,135.80682c0,0.57403 0,6 0,6c0,0 3.2404,-8.2404 4,-9c6.46556,-6.46556 21.91491,-10.08509 28,-4c2.67133,2.67133 -9.18942,2 -10,2c-6.39201,0 -13.98449,-6.03103 -18,2c-0.76896,1.53792 -0.30484,16.84758 0,17c7.98862,3.99431 22.95086,-10.04914 18,-15c-0.66667,-0.66667 -3.33333,0.66667 -4,0c-5.90622,-5.90622 -4,6.18127 -4,11\"></path><path stroke=\"rgb(255,142,0)\" stroke-width=\"2\" fill=\"none\" d=\"M223,131.80682c0,-4.62548 -5.03929,-3.84285 -6,0c-1.58231,6.32922 6.73401,25.26599 14,18c0.42441,-0.42441 -0.19517,-4.4145 0,-5c2.66775,-8.00326 -0.45066,-10.90131 -3,-16c-0.01206,-0.02413 -7.81677,-0.36647 -8,0c-0.29814,0.59628 0.3698,1.4453 0,2c-0.94475,1.41712 -3.33497,18.33252 -2,19c2.32766,1.16383 5.06477,3.06477 7,5c1.35442,1.35442 1.60355,3.79882 4,3c7.51719,-2.50573 3.83722,-28.91861 -8,-23c-2.49031,1.24515 -5.88455,14.55772 -3,16c11.47818,5.73909 11.62877,-12 3,-12\"></path><path stroke=\"rgb(255,142,0)\" stroke-width=\"2\" fill=\"none\" d=\"M562,126.80682c0.33333,0.33333 0.66667,0.66667 1,1\"></path></svg>`\n     this.initSVGInteraction()\n  }\n  \n  livelyMigrate(other) {\n    // TODO: should include:\n    // - strokes\n    // - autosave path\n    // (- history)\n  }\n}\n      \n\n     \n      "]}