{"version":3,"file":"svg-blueprint.mjs","sources":["../src/settings.js","../src/point.js","../src/dom.js","../src/Point.js","../src/Pointer.js","../src/pointers.js","../src/Blueprint.js","../src/template.js","../src/templates/blueprint.js"],"sourcesContent":["/**\r\n * Defaults settings.\r\n *\r\n * @type {object}\r\n */\r\nconst settings = {\r\n  width: \"400px\",\r\n  height: \"300px\",\r\n  parentElement: null,\r\n  parentSelector: \"body\",\r\n  className: \"svg-blueprint\",\r\n  backgroundColor: \"#3177C6\",\r\n  gridColor: \"#fff\",\r\n  gridOpacity: 0.3,\r\n  cursorColor: \"#0b64c4\",\r\n  cursorOpacity: 1,\r\n  axisColor: \"#f4b916\",\r\n  axisOpacity: 0.5,\r\n  nonScalingStroke: true,\r\n  strokeWidth: 2,\r\n  zoomFactor: 0.05,\r\n  zoomDirection: 1,\r\n  zoomLimit: { min: 0.0001, max: 10000 },\r\n  fitPadding: 42,\r\n  stroke: \"#fff\",\r\n  fill: \"none\",\r\n  statusbarStyle: {\r\n    left: \"5px\",\r\n    bottom: \"5px\",\r\n    padding: \"5px\",\r\n    color: \"#222\",\r\n    \"background-color\": \"#fff\",\r\n    \"border-radius\": \"5px\",\r\n    \"font-family\": \"monospace\",\r\n    \"text-transform\": \"uppercase\"\r\n  }\r\n};\r\n\r\nexport default settings;\r\n","/**\r\n * Point class.\r\n */\r\nclass Point {\r\n  /**\r\n   * Point class constructor.\r\n   *\r\n   * - new Point()                // { x: 0 , y: 0  }\r\n   * - new Point([])              // { x: 0 , y: 0  }\r\n   * - new Point(42)              // { x: 42, y: 0  }\r\n   * - new Point([ 42 ])          // { x: 42, y: 0  }\r\n   * - new Point(42, 10)          // { x: 42, y: 10 }\r\n   * - new Point([ 42, 10 ])      // { x: 42, y: 10 }\r\n   * - new Point({ x: 42, y:10 }) // { x: 42, y: 10 }\r\n   *\r\n   * @param {float|array|Point} [x=0]\r\n   * @param {float}             [y=0]\r\n   */\r\n  constructor(x = 0, y = 0) {\r\n    // input format\r\n    if (Array.isArray(x)) {\r\n      y = x[1] || 0;\r\n      x = x[0] || 0;\r\n    } else if (x.x !== undefined) {\r\n      y = x.y || 0;\r\n      x = x.x || 0;\r\n    }\r\n\r\n    /** @type {float} X value. */\r\n    this.x = parseFloat(x);\r\n\r\n    /** @type {float} Y value. */\r\n    this.y = parseFloat(y);\r\n  }\r\n\r\n  /**\r\n   * Add point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  add(point) {\r\n    const p1 = new Point(point);\r\n    return new Point(this.x + p1.x, this.y + p1.y);\r\n  }\r\n\r\n  /**\r\n   * Substract point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  sub(point) {\r\n    const p1 = new Point(point);\r\n    return new Point(this.x - p1.x, this.y - p1.y);\r\n  }\r\n\r\n  /**\r\n   * Multiply point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  mult(point) {\r\n    const p1 = new Point(point, point);\r\n    return new Point(this.x * p1.x, this.y * p1.y);\r\n  }\r\n\r\n  /**\r\n   * Divide point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  div(point) {\r\n    const p1 = new Point(point, point);\r\n    return new Point(this.x / p1.x, this.y / p1.y);\r\n  }\r\n\r\n  /**\r\n   * Return negative point.\r\n   *\r\n   * @return {Point}\r\n   */\r\n  neg() {\r\n    return new Point(-this.x, -this.y);\r\n  }\r\n\r\n  /**\r\n   * Return the distance betwen the two points.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {float}\r\n   */\r\n  distance(point) {\r\n    const diff = this.sub(point);\r\n    const mult = diff.mult(diff);\r\n    return Math.sqrt(mult.x + mult.y);\r\n  }\r\n\r\n  /**\r\n   * Return vector midpoint.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {float}\r\n   */\r\n  midpoint(point) {\r\n    return this.add(new Point(point).sub(this).mult(0.5));\r\n  }\r\n\r\n  /**\r\n   * Return the values as array.\r\n   *\r\n   * @return {array}\r\n   */\r\n  toArray() {\r\n    return [this.x, this.y];\r\n  }\r\n\r\n  /**\r\n   * Return a clone.\r\n   *\r\n   * @return {Point}\r\n   */\r\n  clone() {\r\n    return new Point(this.x, this.y);\r\n  }\r\n}\r\n\r\nexport default Point;\r\n","/**\r\n * XML namespace.\r\n *\r\n * @type {string}\r\n */\r\nconst xmlns = \"http://www.w3.org/2000/svg\";\r\n\r\n/**\r\n * Support passive event listener?\r\n *\r\n * @type {bool}\r\n */\r\nlet supportsPassiveEventListener = false;\r\n\r\ntry {\r\n  const opts = Object.defineProperty({}, \"passive\", {\r\n    get: function() {\r\n      return (supportsPassiveEventListener = true);\r\n    }\r\n  });\r\n  window.addEventListener(\"testPassive\", null, opts);\r\n  window.removeEventListener(\"testPassive\", null, opts);\r\n} catch (e) {\r\n  /* test fail... */\r\n}\r\n\r\n/**\r\n * Add passive event listener.\r\n *\r\n * @param {Element}      element\r\n * @param {array|string} name\r\n * @param {function}     [callback=null]\r\n */\r\nfunction addPassiveEventListener(element, name, callback) {\r\n  const capture = supportsPassiveEventListener ? { passive: true } : false;\r\n  let names = name;\r\n\r\n  if (typeof names === \"string\") {\r\n    names = names.trim().split(/[\\s,]+/);\r\n  }\r\n\r\n  names.forEach(name => {\r\n    if (callback === null) {\r\n      element.removeEventListener(name, callback, capture);\r\n    } else {\r\n      element.addEventListener(name, callback, capture);\r\n    }\r\n  });\r\n}\r\n\r\n/**\r\n * Add (passive) event(s) listener.\r\n *\r\n * @param {Element}  element\r\n * @param {string}   name\r\n * @param {function} [callback=null]\r\n */\r\nfunction addEvent(element, name, callback = null) {\r\n  if (typeof name === \"string\") {\r\n    addPassiveEventListener(element, name, callback);\r\n    return;\r\n  }\r\n\r\n  const keys = Object.keys(name);\r\n\r\n  for (let key of keys) {\r\n    addPassiveEventListener(element, key, name[key]);\r\n  }\r\n}\r\n\r\n/**\r\n * Set style(s).\r\n *\r\n * Setting a NULL value remove the property.\r\n *\r\n * @param {Element}       element\r\n * @param {string|object} name\r\n * @param {null|mixed}    [value=null]\r\n */\r\nfunction setStyle(element, name, value = null) {\r\n  if (typeof name === \"string\") {\r\n    if (value === null) {\r\n      element.style.removeProperty(name);\r\n    } else {\r\n      element.style.setProperty(name, value);\r\n    }\r\n    return;\r\n  }\r\n\r\n  const keys = Object.keys(name);\r\n\r\n  for (let key of keys) {\r\n    setStyle(element, key, name[key]);\r\n  }\r\n}\r\n\r\n/**\r\n * Set transform(s).\r\n *\r\n * - setTransform(element);                // remove all\r\n * - setTransform(element, null);          // remove all\r\n * - setTransform(element, 'scale');       // remove \"scale(x)\" in transform attribute\r\n * - setTransform(element, 'scale', null); // remove \"scale(x)\" in transform attribute\r\n * - setTransform(element, 'scale', 10);   // set \"scale(10)\" in transform attribute\r\n *\r\n * @param {Element}            element\r\n * @param {null|string|object} type\r\n * @param {null|mixed}         [value=null]\r\n */\r\nfunction setTransform(element, type = null, value = null) {\r\n  // remove transform attribute\r\n  if (type === null) {\r\n    setAttribute(element, \"transform\", null);\r\n    return;\r\n  }\r\n\r\n  // get current value\r\n  let transform = element.getAttribute(\"transform\") || \"\";\r\n\r\n  // ...\r\n  let types = {};\r\n\r\n  if (typeof type === \"string\") {\r\n    types[type] = value;\r\n  } else {\r\n    types = type;\r\n  }\r\n\r\n  const keys = Object.keys(types);\r\n\r\n  for (let key of keys) {\r\n    const value = types[key];\r\n    // remove transform type\r\n    transform = transform.replace(new RegExp(`${key}\\\\([^)]+\\\\)`, \"g\"), \"\");\r\n    if (value === null) {\r\n      continue;\r\n    }\r\n    // add new value\r\n    if (Array.isArray(value)) {\r\n      transform += `${key}(${value.join(\" \")}) `;\r\n    } else {\r\n      transform += `${key}(${value}) `;\r\n    }\r\n  }\r\n\r\n  // cleanup\r\n  transform = transform.replace(/\\s+/, \" \").trim();\r\n\r\n  // set new transform\r\n  setAttribute(element, \"transform\", transform);\r\n}\r\n\r\n/**\r\n * Set attribute(s).\r\n *\r\n * - Setting a NULL value remove the attribute.\r\n * - If the name parameter is \"style\", setStyle(element, value) is called.\r\n * - If the name parameter is \"event\", addEvent(element, value) is called.\r\n * - If the name parameter is \"transform\", setTransform(element, value) is called.\r\n *\r\n * @param {Element}       element\r\n * @param {string|object} name\r\n * @param {null|mixed}    [value=null]\r\n */\r\nfunction setAttribute(element, name, value = null) {\r\n  if (typeof name === \"string\") {\r\n    if (value === null) {\r\n      element.removeAttribute(name);\r\n    } else {\r\n      element.setAttribute(name, value);\r\n    }\r\n    return;\r\n  }\r\n\r\n  const keys = Object.keys(name);\r\n\r\n  for (let key of keys) {\r\n    if (key === \"style\") {\r\n      setStyle(element, name[key]);\r\n    } else if (key === \"event\") {\r\n      addEvent(element, name[key]);\r\n    } else if (key === \"transform\") {\r\n      setTransform(element, name[key]);\r\n    } else {\r\n      setAttribute(element, key, name[key]);\r\n    }\r\n  }\r\n}\r\n\r\n/**\r\n * Create en return a DOM Element from a string.\r\n *\r\n * @param {string} string\r\n * @param {string} [mimeType=\"application/xml\"]\r\n *\r\n * @return {Element}\r\n */\r\nfunction fromString(string, mimeType = \"application/xml\") {\r\n  return new DOMParser().parseFromString(string, mimeType);\r\n}\r\n\r\n/**\r\n * Create en return a DOM Element.\r\n *\r\n * @param {string}      string\r\n * @param {null|object} [attributes=null]\r\n *\r\n * @return {Element}\r\n */\r\nfunction createElement(name, attributes = null) {\r\n  const element = document.createElement(name);\r\n\r\n  if (attributes !== null) {\r\n    setAttribute(element, attributes);\r\n  }\r\n\r\n  return element;\r\n}\r\n\r\n/**\r\n * Create en return a SVG Element.\r\n *\r\n * @param {string}      string\r\n * @param {null|object} [attributes=null]\r\n *\r\n * @return {SVGElement}\r\n */\r\nfunction createSVGElement(name, attributes = null) {\r\n  let element = null;\r\n\r\n  if (name.charAt(0) === \"<\") {\r\n    const doc = fromString(`<svg xmlns=\"${xmlns}\">${name}</svg>`);\r\n    element = doc.documentElement.firstChild;\r\n  } else {\r\n    element = document.createElementNS(xmlns, name);\r\n  }\r\n\r\n  if (attributes !== null) {\r\n    setAttribute(element, attributes);\r\n  }\r\n\r\n  return element;\r\n}\r\n\r\nexport {\r\n  xmlns,\r\n  setStyle,\r\n  setAttribute,\r\n  setTransform,\r\n  fromString,\r\n  createElement,\r\n  createSVGElement,\r\n  addPassiveEventListener,\r\n  addEvent\r\n};\r\n","/**\r\n * Point class.\r\n */\r\nclass Point {\r\n  /**\r\n   * Point class constructor.\r\n   *\r\n   * - new Point()                // { x: 0 , y: 0  }\r\n   * - new Point([])              // { x: 0 , y: 0  }\r\n   * - new Point(42)              // { x: 42, y: 0  }\r\n   * - new Point([ 42 ])          // { x: 42, y: 0  }\r\n   * - new Point(42, 10)          // { x: 42, y: 10 }\r\n   * - new Point([ 42, 10 ])      // { x: 42, y: 10 }\r\n   * - new Point({ x: 42, y:10 }) // { x: 42, y: 10 }\r\n   *\r\n   * @param {float|array|Point} [x=0]\r\n   * @param {float}             [y=0]\r\n   */\r\n  constructor(x = 0, y = 0) {\r\n    // input format\r\n    if (Array.isArray(x)) {\r\n      y = x[1] || 0;\r\n      x = x[0] || 0;\r\n    } else if (x.x !== undefined) {\r\n      y = x.y || 0;\r\n      x = x.x || 0;\r\n    }\r\n\r\n    /** @type {float} X value. */\r\n    this.x = parseFloat(x);\r\n\r\n    /** @type {float} Y value. */\r\n    this.y = parseFloat(y);\r\n  }\r\n\r\n  /**\r\n   * Add point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  add(point) {\r\n    const p1 = new Point(point);\r\n    return new Point(this.x + p1.x, this.y + p1.y);\r\n  }\r\n\r\n  /**\r\n   * Substract point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  sub(point) {\r\n    const p1 = new Point(point);\r\n    return new Point(this.x - p1.x, this.y - p1.y);\r\n  }\r\n\r\n  /**\r\n   * Multiply point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  mult(point) {\r\n    const p1 = new Point(point, point);\r\n    return new Point(this.x * p1.x, this.y * p1.y);\r\n  }\r\n\r\n  /**\r\n   * Divide point and return new Point.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {Point}\r\n   */\r\n  div(point) {\r\n    const p1 = new Point(point, point);\r\n    return new Point(this.x / p1.x, this.y / p1.y);\r\n  }\r\n\r\n  /**\r\n   * Return negative point.\r\n   *\r\n   * @return {Point}\r\n   */\r\n  neg() {\r\n    return new Point(-this.x, -this.y);\r\n  }\r\n\r\n  /**\r\n   * Return the distance betwen the two points.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {float}\r\n   */\r\n  distance(point) {\r\n    const diff = this.sub(point);\r\n    const mult = diff.mult(diff);\r\n    return Math.sqrt(mult.x + mult.y);\r\n  }\r\n\r\n  /**\r\n   * Return vector midpoint.\r\n   *\r\n   * @param  {float|array|Point} point\r\n   * @return {float}\r\n   */\r\n  midpoint(point) {\r\n    return this.add(new Point(point).sub(this).mult(0.5));\r\n  }\r\n\r\n  /**\r\n   * Return the values as array.\r\n   *\r\n   * @return {array}\r\n   */\r\n  toArray() {\r\n    return [this.x, this.y];\r\n  }\r\n\r\n  /**\r\n   * Return a clone.\r\n   *\r\n   * @return {Point}\r\n   */\r\n  clone() {\r\n    return new Point(this.x, this.y);\r\n  }\r\n}\r\n\r\nexport default Point;\r\n","import Point from \"./Point\";\r\n\r\n/**\r\n * Pointer class.\r\n */\r\nclass Pointer {\r\n  /**\r\n   * Pointer class constructor.\r\n   */\r\n  constructor(pointerEvent) {\r\n    this.event = pointerEvent;\r\n    this.id = pointerEvent.pointerId;\r\n    this.position = new Point();\r\n    this.movement = new Point();\r\n    this.distance = 0;\r\n    this.down = false;\r\n    this.downTime = 0;\r\n    this.upTime = 0;\r\n    this.tapCount = 0;\r\n    this.tapDuration = 0;\r\n    this.panning = false;\r\n    this.panDistance = 0;\r\n    this.panStartPosition = 0;\r\n    this.panOffsets = new Point();\r\n    this.pinch = null;\r\n    this.pinchRatio = 1;\r\n    this.pinchDistance = 0;\r\n    this.pinchMidpoint = 0;\r\n    this.pinchOffset = 0;\r\n    this.primary = false;\r\n  }\r\n\r\n  /**\r\n   * Clone and return the new pointer.\r\n   *\r\n   * @return {Pointer}\r\n   */\r\n  clone() {\r\n    const clone = {};\r\n    const keys = Object.keys(this);\r\n\r\n    for (let key of keys) {\r\n      let value = this[key];\r\n\r\n      if (value && value instanceof Point) {\r\n        value = value.clone();\r\n      }\r\n\r\n      clone[key] = value;\r\n    }\r\n\r\n    return clone;\r\n  }\r\n}\r\n\r\nexport default Pointer;\r\n","import { setStyle, addEvent } from \"./dom\";\r\nimport Pointer from \"./Pointer\";\r\nimport Point from \"./Point\";\r\n\r\n/**\r\n * Defaults settings.\r\n *\r\n * @type {object}\r\n */\r\nconst settings = {\r\n  panThreshold: 10, // px\r\n  tapThreshold: 200, // ms\r\n  tapTimeout: 500 // ms\r\n};\r\n\r\n/**\r\n * Pointers event types list.\r\n *\r\n * @type {array}\r\n */\r\nconst eventTypes = [\r\n  \"pointerover\",\r\n  \"pointerenter\",\r\n  \"pointerdown\",\r\n  \"pointermove\",\r\n  \"pointerup\",\r\n  \"pointercancel\",\r\n  \"pointerout\",\r\n  \"pointerleave\",\r\n  \"gotpointercapture\",\r\n  \"lostpointercapture\"\r\n];\r\n\r\n/**\r\n * Pointers class.\r\n */\r\nclass Pointers {\r\n  /**\r\n   * Pointers class constructor.\r\n   *\r\n   * @param {Element} element\r\n   */\r\n  constructor(target, options = {}) {\r\n    /** @type {Element} Target element. */\r\n    this.target = target;\r\n\r\n    /** @type {object} Current settings. */\r\n    this.settings = { ...settings, ...options };\r\n\r\n    /** @type {array} Callbacks list. */\r\n    this.callbacks = [];\r\n\r\n    /** @type {Map} Pointerss collection. */\r\n    this.pointers = new Map();\r\n\r\n    /** @type {int} Tap counter. */\r\n    this.tapCount = 0;\r\n\r\n    /** @type {int} Tap timeout ID. */\r\n    this.tapTimeout = null;\r\n\r\n    /** @type {int} Wheel timeout ID. */\r\n    this.wheelTimeout = null;\r\n\r\n    // disable browser touch events on the target element\r\n    setStyle(target, \"touch-action\", \"none\");\r\n\r\n    // track all pointers events\r\n    addEvent(target, eventTypes.join(\",\"), pointerEvent => {\r\n      this.trackPointer(pointerEvent);\r\n    });\r\n\r\n    // remove pointer on leave/cancel/lostcapture\r\n    addEvent(\r\n      target,\r\n      \"pointerleave pointercancel lostpointercapture\",\r\n      pointerEvent => {\r\n        this.deletePointer(pointerEvent.pointerId);\r\n      }\r\n    );\r\n\r\n    // mouse wheel (not a pointer event, add for convenience)\r\n    addEvent(target, \"wheel\", mouseEvent => {\r\n      this.onMouseWheel(mouseEvent);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Has pointer id.\r\n   *\r\n   * @param {int} id\r\n   *\r\n   * @return {Boolean}\r\n   */\r\n  hasPointer(id) {\r\n    return this.pointers.has(id);\r\n  }\r\n\r\n  /**\r\n   * Get pointer by id.\r\n   *\r\n   * @param {int} id\r\n   *\r\n   * @return {null|Pointer}\r\n   */\r\n  getPointer(id) {\r\n    return this.pointers.get(id);\r\n  }\r\n\r\n  /**\r\n   * Set new pointer.\r\n   *\r\n   * @param {Pointer} pointer\r\n   */\r\n  setPointer(pointer) {\r\n    this.pointers.set(pointer.id, pointer);\r\n  }\r\n\r\n  /**\r\n   * Delete pointer by id.\r\n   *\r\n   * @param {int} id\r\n   */\r\n  deletePointer(id) {\r\n    if (this.pointers.has(id)) {\r\n      this.pointers.delete(id);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Return the relative position of the pointer from the target element.\r\n   *\r\n   * @param {PointerEvent} pointerEvent\r\n   *\r\n   * @return {Point}\r\n   */\r\n  getPosition(pointerEvent) {\r\n    const offsets = this.target.getBoundingClientRect();\r\n    return new Point(\r\n      pointerEvent.pageX - offsets.left,\r\n      pointerEvent.pageY - offsets.top\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Tap recognizer.\r\n   *\r\n   * @param {string}  eventType\r\n   * @param {Pointer} pointer\r\n   */\r\n  tapRecognizer(eventType, pointer) {\r\n    if (eventType !== \"up\") {\r\n      return;\r\n    }\r\n\r\n    // calculate duration between up and down event\r\n    const tapDuration = pointer.upTime - pointer.downTime;\r\n\r\n    if (tapDuration > this.settings.tapThreshold) {\r\n      return; // time out\r\n    }\r\n\r\n    // clear tap timeout if any\r\n    this.tapTimeout && clearTimeout(this.tapTimeout);\r\n\r\n    // increment tap counter\r\n    pointer.tapCount = ++this.tapCount;\r\n    pointer.tapDuration = tapDuration;\r\n\r\n    // emit tap start event\r\n    if (this.tapCount === 1) {\r\n      this.emit(\"tap.start\", pointer.clone());\r\n    }\r\n\r\n    // emit tap event...\r\n    this.emit(\"tap\", pointer.clone());\r\n\r\n    // watch for tap end event\r\n    this.tapTimeout = setTimeout(() => {\r\n      this.emit(\"tap.end\", pointer.clone());\r\n      this.tapCount = 0;\r\n    }, this.settings.tapTimeout);\r\n  }\r\n\r\n  /**\r\n   * Pan recognizer.\r\n   *\r\n   * @param {string}  eventType\r\n   * @param {Pointer} pointer\r\n   */\r\n  panRecognizer(eventType, pointer) {\r\n    if (eventType === \"move\") {\r\n      if (pointer.panStartPosition) {\r\n        pointer.panOffsets = pointer.position.sub(pointer.panStartPosition);\r\n        pointer.panDistance = pointer.panStartPosition.distance(\r\n          pointer.position\r\n        );\r\n        if (pointer.panning) {\r\n          this.emit(\"pan.move\", pointer.clone());\r\n        } else if (pointer.panDistance > this.settings.panThreshold) {\r\n          pointer.panning = true;\r\n          this.emit(\"pan.start\", pointer.clone());\r\n        }\r\n      }\r\n      return;\r\n    }\r\n\r\n    if (eventType === \"down\") {\r\n      if (!pointer.panStartPosition) {\r\n        pointer.panStartPosition = pointer.position.clone();\r\n      }\r\n      return;\r\n    }\r\n\r\n    if ([\"up\", \"leave\", \"cancel\", \"lostcapture\"].indexOf(eventType) !== -1) {\r\n      if (pointer.panStartPosition) {\r\n        if (pointer.panning) {\r\n          this.emit(\"pan.end\", pointer.clone());\r\n        }\r\n        pointer.panOffsets = new Point();\r\n        pointer.panStartPosition = 0;\r\n        pointer.panDistance = 0;\r\n        pointer.panning = false;\r\n      }\r\n      return;\r\n    }\r\n  }\r\n\r\n  onPinch(p1, p2) {\r\n    const pinchDistance = p1.position.distance(p2.position);\r\n    const pinchMidpoint = p1.position.midpoint(p2.position);\r\n    const pinchOffset = p1.pinchOffset || pinchDistance;\r\n    const pinchRatio = pinchDistance / p1.pinchOffset;\r\n    Object.assign(p1, {\r\n      pinchDistance,\r\n      pinchMidpoint,\r\n      pinchOffset,\r\n      pinchRatio\r\n    });\r\n    Object.assign(p2, {\r\n      pinchDistance,\r\n      pinchMidpoint,\r\n      pinchOffset,\r\n      pinchRatio\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Pinch recognizer.\r\n   *\r\n   * @param {string}  eventType\r\n   * @param {Pointer} pointer\r\n   */\r\n  pinchRecognizer(eventType, pointer) {\r\n    if (eventType === \"move\") {\r\n      if (pointer.pinch) {\r\n        this.onPinch(pointer, pointer.pinch);\r\n        this.emit(\"pinch.move\", pointer.clone());\r\n      }\r\n      return;\r\n    }\r\n\r\n    if (eventType === \"down\") {\r\n      let p1 = null;\r\n      this.pointers.forEach(p => {\r\n        if (p1 || !p.down || p.pinch || p.id === pointer.id) return;\r\n        p1 = p;\r\n      });\r\n      if (p1) {\r\n        p1.pinch = pointer;\r\n        pointer.pinch = p1;\r\n        this.onPinch(p1, pointer);\r\n        this.emit(\"pinch.start\", pointer.clone());\r\n      }\r\n      return;\r\n    }\r\n\r\n    const pinchReset = point => {\r\n      point.pinch = null;\r\n      point.pinchRatio = 1;\r\n      point.pinchDistance = 0;\r\n      point.pinchMidpoint = 0;\r\n      point.pinchOffset = 0;\r\n    };\r\n\r\n    if (eventType === \"up\") {\r\n      if (pointer.pinch) {\r\n        this.emit(\"pinch.end\", pointer.clone());\r\n        pinchReset(pointer.pinch);\r\n        pinchReset(pointer);\r\n      }\r\n      return;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Track pointer event.\r\n   *\r\n   * @param {PointersEvent} pointerEvent\r\n   */\r\n  trackPointer(pointerEvent) {\r\n    // event type\r\n    const eventType = pointerEvent.type.replace(\"pointer\", \"\");\r\n\r\n    // get the pointer\r\n    let pointer = this.getPointer(pointerEvent.pointerId);\r\n\r\n    // get current position\r\n    const position = this.getPosition(pointerEvent);\r\n\r\n    // add new pointer if not already set\r\n    if (!pointer) {\r\n      pointer = new Pointer(pointerEvent);\r\n      pointer.primary = pointerEvent.isPrimary;\r\n      pointer.position = position;\r\n      this.setPointer(pointer);\r\n    }\r\n\r\n    // update pointer\r\n    if (eventType === \"move\") {\r\n      pointer.distance = pointer.position.distance(position);\r\n      pointer.movement = position.sub(pointer.position);\r\n      pointer.position = position;\r\n    } else if (eventType === \"down\") {\r\n      pointer.downTime = Date.now();\r\n      pointer.down = true;\r\n    } else if (eventType === \"up\") {\r\n      pointer.upTime = Date.now();\r\n      pointer.down = false;\r\n    }\r\n\r\n    // emit event\r\n    this.emit(eventType, pointer.clone());\r\n\r\n    // recognizers\r\n    this.tapRecognizer(eventType, pointer);\r\n    this.panRecognizer(eventType, pointer);\r\n    this.pinchRecognizer(eventType, pointer);\r\n  }\r\n\r\n  /**\r\n   * On mouse wheel...\r\n   *\r\n   * @param {MouseEvent} mouseEvent\r\n   */\r\n  onMouseWheel(mouseEvent) {\r\n    const delta = mouseEvent.deltaY > 0 ? 1 : -1;\r\n    const pointer = new Pointer(mouseEvent);\r\n    pointer.position = this.getPosition(mouseEvent);\r\n    pointer.delta = delta;\r\n\r\n    if (this.wheelTimeout === null) {\r\n      this.emit(\"wheel.start\", pointer);\r\n    }\r\n\r\n    this.emit(\"wheel.move\", pointer);\r\n    clearTimeout(this.wheelTimeout);\r\n\r\n    this.wheelTimeout = setTimeout(() => {\r\n      this.wheelTimeout = null;\r\n      this.emit(\"wheel.end\", pointer);\r\n    }, 120);\r\n  }\r\n\r\n  /**\r\n   * Register event callback.\r\n   *\r\n   * @param {array|string} type\r\n   * @param {function}     func\r\n   */\r\n  on(type, func) {\r\n    let types = type;\r\n\r\n    if (typeof types === \"string\") {\r\n      types = types.trim().split(/[\\s,]+/);\r\n    }\r\n\r\n    types.forEach(type => {\r\n      this.callbacks.push({ type, func });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Emit an event.\r\n   *\r\n   * @param {string} type\r\n   * @param {object} [data={}]\r\n   */\r\n  emit(type, data = {}) {\r\n    this.callbacks.forEach(callback => {\r\n      if (callback.type === type || callback.type === \"*\") {\r\n        callback.func({ type, data });\r\n      }\r\n    });\r\n  }\r\n}\r\n\r\nexport default Pointers;\r\n","import settings from \"./settings\";\r\nimport templates from \"./templates\";\r\nimport Point from \"./point\";\r\nimport Pointers from \"./pointers\";\r\nimport { setStyle, setAttribute, setTransform, createSVGElement } from \"./dom\";\r\n\r\n// Unique ID; Incremented each time a Blueprint class is instanciated.\r\nlet uid = 0;\r\n\r\n// Firefox detection\r\nconst isFirefox = !!navigator.userAgent.match(/firefox/i);\r\n\r\n/**\r\n * Get and check parent Element from settings object.\r\n *\r\n * @param  {object}  params\r\n * @param  {Element} params.parentElement\r\n * @param  {string}  params.parentSelector\r\n * @return {Element}\r\n * @throws {Error}\r\n */\r\nfunction getParent({ parentElement, parentSelector }) {\r\n  let parent = null;\r\n\r\n  if (parentElement !== null) {\r\n    if (!(parentElement instanceof Element)) {\r\n      throw new Error(\"Option { parentElement } must be of type Element.\");\r\n    }\r\n\r\n    return parentElement;\r\n  }\r\n\r\n  parent = document.querySelector(parentSelector);\r\n\r\n  if (!parent) {\r\n    throw new Error(`No parent found with the selector [ ${parentSelector} ]`);\r\n  }\r\n\r\n  return parent;\r\n}\r\n\r\n/**\r\n * Blueprint class.\r\n */\r\nclass Blueprint {\r\n  /**\r\n   * Blueprint constructor.\r\n   *\r\n   * @param {object} [options={}]\r\n   */\r\n  constructor(options = {}) {\r\n    /** @type {int} Unique ID. */\r\n    this.uid = uid++;\r\n\r\n    /** @type {object} Local settings. */\r\n    this.settings = { ...settings, ...options };\r\n\r\n    /** @type {Element} Parent DOM Element. */\r\n    this.parent = getParent(this.settings);\r\n\r\n    /** @type {object} Collection of DOM Elements. */\r\n    this.elements = templates.blueprint({ ...this.settings, uid });\r\n\r\n    /** @type {Point} Current position. */\r\n    this.position = new Point(0, 0);\r\n\r\n    /** @type {Point} Cursor position. */\r\n    this.cursor = new Point(0, 0);\r\n\r\n    /** @type {Point} Cursor coordinates. */\r\n    this.cursorCoords = new Point(0, 0);\r\n\r\n    /** @type {float} Current scale factor. */\r\n    this.scale = 1;\r\n\r\n    /** @type {int} Grid size. */\r\n    this.gridSize = 100;\r\n\r\n    /** @type {Pointers} Pointers instance. */\r\n    this.pointers = new Pointers(this.parent);\r\n\r\n    // append the blueprint element to parent element\r\n    this.parent.appendChild(this.elements.blueprint);\r\n\r\n    // statusbar styling\r\n    setStyle(this.elements.statusbar, this.settings.statusbarStyle);\r\n\r\n    // primary cursor tracking\r\n    this.pointers.on(\"move\", event => {\r\n      if (event.data.primary) {\r\n        this.cursorCoords = this.getRelativePosition(event.data.position);\r\n        this.redrawStatusbar();\r\n      }\r\n    });\r\n\r\n    // tap\r\n    this.pointers.on(\"tap.end\", event => {\r\n      if (event.data.tapCount === 2) {\r\n        this.fit();\r\n      }\r\n    });\r\n\r\n    // pan\r\n    let panId = null;\r\n\r\n    this.pointers.on(\"pan.start\", event => {\r\n      if (panId !== null) return;\r\n      panId = event.data.id;\r\n      this.pan(event.data.panOffsets);\r\n      this.updateCursorPosition({ position: event.data.position, show: true });\r\n    });\r\n\r\n    this.pointers.on(\"pan.move\", event => {\r\n      if (panId !== event.data.id) return;\r\n      this.pan(event.data.movement);\r\n      this.updateCursorPosition({ position: event.data.position, show: true });\r\n    });\r\n\r\n    this.pointers.on(\"pan.end\", event => {\r\n      if (panId !== event.data.id) return;\r\n      this.hide(\"cursor\");\r\n      panId = null;\r\n    });\r\n\r\n    // pinch\r\n    let pinchRatio = null;\r\n    let pinchMidpoint = null;\r\n\r\n    this.pointers.on(\"pinch.start\", event => {\r\n      panId = null; // end pan...\r\n      pinchRatio = 1; //event.data.pinchRatio;\r\n      pinchMidpoint = event.data.pinchMidpoint;\r\n      this.updateCursorPosition({ position: pinchMidpoint, show: true });\r\n    });\r\n\r\n    this.pointers.on(\"pinch.move\", event => {\r\n      panId = null; // end pan...\r\n      this.zoom({\r\n        ratio: this.scale + event.data.pinchRatio - pinchRatio,\r\n        target: pinchMidpoint\r\n      });\r\n      pinchRatio = event.data.pinchRatio;\r\n      this.updateCursorPosition({ position: pinchMidpoint, show: true });\r\n    });\r\n\r\n    this.pointers.on(\"pinch.end\", () => {\r\n      this.hide(\"cursor\");\r\n    });\r\n\r\n    // mouse wheel\r\n    this.pointers.on(\"wheel.start\", event => {\r\n      this.updateCursorPosition({ position: event.data.position, show: true });\r\n    });\r\n\r\n    this.pointers.on(\"wheel.move\", event => {\r\n      this.zoom({ delta: event.data.delta, target: event.data.position });\r\n      this.updateCursorPosition({ position: event.data.position, show: true });\r\n    });\r\n\r\n    this.pointers.on(\"wheel.end\", () => {\r\n      this.hide(\"cursor\");\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Show/Hide an element.\r\n   *\r\n   * - show(\"axis\");\r\n   * - show(\"axis grid\");\r\n   * - show(\"axis grid\", false);\r\n   * - show([\"axis\", \"grid\"], true);\r\n   *\r\n   * @param {string|array} what axis, grid, etc...\r\n   * @param {bool}         [display=true]\r\n   */\r\n  show(what, display = true) {\r\n    if (!Array.isArray(what)) {\r\n      what = what.split(/[\\s,]+/);\r\n    }\r\n\r\n    what.forEach(key => {\r\n      if (this.elements[key]) {\r\n        setStyle(this.elements[key], \"display\", display ? null : \"none\");\r\n      }\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Hide/Show an element.\r\n   *\r\n   * - hide(\"axis\");\r\n   * - hide(\"axis grid\");\r\n   * - hide(\"axis grid\", false);\r\n   * - hide([\"axis\", \"grid\"], true);\r\n   *\r\n   * @param {string} what axis, grid, etc...\r\n   * @param {bool}   [hide=true]\r\n   */\r\n  hide(what, hide = true) {\r\n    this.show(what, !hide);\r\n  }\r\n\r\n  /**\r\n   * Redraw the statusbar.\r\n   */\r\n  redrawStatusbar() {\r\n    let zoom = Math.round(this.scale * 100);\r\n    let decimals = zoom.toString().length - 1;\r\n    const x = this.cursorCoords.x.toFixed(decimals);\r\n    const y = this.cursorCoords.y.toFixed(decimals);\r\n\r\n    if (zoom < 1) {\r\n      decimals = this.zoomLimit.min.toFixed(20).replace(/0+$/, \"\").length - 4;\r\n      zoom = (this.scale * 100).toFixed(decimals);\r\n    }\r\n\r\n    this.elements.position.innerText = `x: ${x}, y: ${y}`;\r\n    this.elements.zoom.innerText = `${zoom} %`;\r\n  }\r\n\r\n  /**\r\n   * Redraw the workspace.\r\n   */\r\n  redraw() {\r\n    // translate axis\r\n    setTransform(this.elements.axisX, \"translate\", [0, -this.position.y]);\r\n    setTransform(this.elements.axisY, \"translate\", [-this.position.x, 0]);\r\n\r\n    // translate cursor\r\n    setTransform(this.elements.cursorX, \"translate\", [0, this.cursor.y]);\r\n    setTransform(this.elements.cursorY, \"translate\", [this.cursor.x, 0]);\r\n\r\n    // translate grid\r\n    setAttribute(\r\n      this.elements.gridPattern,\r\n      \"patternTransform\",\r\n      `translate(${-this.position.x}, ${-this.position.y})`\r\n    );\r\n\r\n    // scale grid\r\n    const gridSize = { width: this.gridSize, height: this.gridSize };\r\n    const gridPath = `M ${this.gridSize} 0 L 0 0 0 ${this.gridSize}`;\r\n\r\n    setAttribute(this.elements.gridFill10, gridSize);\r\n    setAttribute(this.elements.gridFill100, gridSize);\r\n    setAttribute(this.elements.gridPattern, gridSize);\r\n    setAttribute(this.elements.gridPattern10, \"d\", gridPath);\r\n    setAttribute(this.elements.gridPattern100, \"d\", gridPath);\r\n\r\n    // scale stroke width\r\n    if (this.settings.nonScalingStroke === true) {\r\n      const strokeWidth = this.settings.strokeWidth / this.scale;\r\n      setStyle(this.elements.workspace, \"stroke-width\", strokeWidth);\r\n    }\r\n\r\n    // translate workspace\r\n    setAttribute(this.elements.workspace, \"viewBox\", [\r\n      this.position.x / this.scale,\r\n      this.position.y / this.scale,\r\n      1 / this.scale,\r\n      1 / this.scale\r\n    ]);\r\n\r\n    // Force redraw to fix blurry lines\r\n    if (isFirefox) {\r\n      const clone = this.elements.workspace.cloneNode(true);\r\n      this.elements.canvas.replaceChild(clone, this.elements.workspace);\r\n      this.elements.bbox = clone.querySelector('[data-key=\"bbox\"]');\r\n      this.elements.workspace = clone;\r\n    }\r\n\r\n    this.redrawStatusbar();\r\n  }\r\n\r\n  /**\r\n   * Update the cursor position.\r\n   *\r\n   * @param {object} [options={}]\r\n   * @param {Point}  options.position\r\n   * @param {bool}   [options.show=false]\r\n   */\r\n  updateCursorPosition({ position, show = false } = {}) {\r\n    this.cursor = new Point(position);\r\n    this.show(\"cursor\", show);\r\n    this.redraw();\r\n  }\r\n\r\n  /**\r\n   * Move the workspace at position.\r\n   *\r\n   * @param {Point} point\r\n   */\r\n  move(point) {\r\n    this.position = new Point(point);\r\n\r\n    this.redraw();\r\n  }\r\n\r\n  /**\r\n   * Move the workspace by offsets.\r\n   *\r\n   * @param {Point} point\r\n   */\r\n  pan(point) {\r\n    this.position = this.position.sub(point);\r\n\r\n    this.redraw();\r\n  }\r\n\r\n  /**\r\n   * Return the center point of the workspace.\r\n   *\r\n   * @return {Point}\r\n   */\r\n  getWorkspaceCenter() {\r\n    return new Point(\r\n      this.elements.blueprint.offsetWidth / 2,\r\n      this.elements.blueprint.offsetHeight / 2\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Return the relative position at current scale.\r\n   *\r\n   * @param {Point} position\r\n   * @param {float} [scale=null]\r\n   *\r\n   * @return {Point}\r\n   */\r\n  getRelativePosition(position, scale = null) {\r\n    scale = scale === null ? this.scale : scale;\r\n    return position.div(scale).add(this.position.div(scale));\r\n  }\r\n\r\n  /**\r\n   * Zoom the workspace.\r\n   *\r\n   * @param {float|object} [scale={}]          Scale ratio or scale options.\r\n   * @param {float}        [scale.ratio=1]     New scale ratio, used by center view etc...\r\n   * @param {float}        [scale.delta=null]  Amount of scale to add, based on zoomFactor setting.\r\n   * @param {object}       [scale.target=null] Zoom target point, by default center of workspace.\r\n   */\r\n  zoom(scale = {}) {\r\n    // old scale\r\n    const oldScale = this.scale;\r\n\r\n    // old way...\r\n    if (typeof scale !== \"object\") {\r\n      scale = { ratio: scale };\r\n    }\r\n\r\n    // merge defaults settings\r\n    scale = { ratio: 1, delta: null, target: null, ...scale };\r\n\r\n    // scale by ratio/delta ?\r\n    if (scale.delta !== null) {\r\n      scale.delta *= this.settings.zoomDirection;\r\n      this.scale += scale.delta * this.settings.zoomFactor * this.scale;\r\n    } else {\r\n      this.scale = scale.ratio;\r\n    }\r\n\r\n    // zoom limit\r\n    if (this.scale < this.settings.zoomLimit.min) {\r\n      this.scale = this.settings.zoomLimit.min;\r\n    } else if (this.scale > this.settings.zoomLimit.max) {\r\n      this.scale = this.settings.zoomLimit.max;\r\n    }\r\n\r\n    // (calculate) new grid size\r\n    let gridSize = this.scale\r\n      .toString()\r\n      .replace(\".\", \"\")\r\n      .replace(/e.*/, \"\")\r\n      .replace(/^0+/, \"\")\r\n      .replace(/^([1-9])/, \"$1.\");\r\n    this.gridSize = parseFloat(gridSize) * 100;\r\n\r\n    // target point, default to center of workspace\r\n    scale.target = scale.target\r\n      ? new Point(scale.target)\r\n      : this.getWorkspaceCenter();\r\n\r\n    // mouse coordinates at current scale\r\n    const coords = this.getRelativePosition(scale.target, oldScale);\r\n\r\n    // new position\r\n    this.position = new Point(\r\n      coords.x * this.scale - scale.target.x,\r\n      coords.y * this.scale - scale.target.y\r\n    );\r\n\r\n    this.redraw();\r\n  }\r\n\r\n  /**\r\n   * Center the view at [0, 0].\r\n   */\r\n  center() {\r\n    this.move(this.getWorkspaceCenter().neg());\r\n  }\r\n\r\n  /**\r\n   * Fit workspace to view.\r\n   */\r\n  fit() {\r\n    let workspace = this.elements.bbox.getBoundingClientRect();\r\n    let width = workspace.width / this.scale;\r\n    let height = workspace.height / this.scale;\r\n\r\n    // no contents...\r\n    if (!width || !height) {\r\n      this.center();\r\n      return;\r\n    }\r\n\r\n    // zoom to fit the view minus the padding\r\n    const padding = this.settings.fitPadding * 2;\r\n    const scaleX = (this.elements.blueprint.offsetWidth - padding) / width;\r\n    const scaleY = (this.elements.blueprint.offsetHeight - padding) / height;\r\n    const scale = Math.min(scaleX, scaleY);\r\n\r\n    this.zoom(scale);\r\n\r\n    // move the workspace at center of the view\r\n    const blueprint = this.elements.blueprint.getBoundingClientRect();\r\n    workspace = this.elements.bbox.getBoundingClientRect();\r\n    width = (blueprint.width - workspace.width) / 2;\r\n    height = (blueprint.height - workspace.height) / 2;\r\n\r\n    this.pan({\r\n      x: -workspace.left + blueprint.left + width,\r\n      y: -workspace.top + blueprint.top + height\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Create an SVG element with default properties.\r\n   *\r\n   * - remove \"stroke-width\" attribute\r\n   * - remove \"stroke-width, stroke, fill\" css properties\r\n   * - set default \"stroke\" and \"fill\" attributes from settings\r\n   * - \"stroke-width, stroke, fill\" can be overwritten by attribute parameter\r\n   *\r\n   * @param {string} name\r\n   * @param {object} [attributes={}]\r\n   *\r\n   * @return {SVGElement}\r\n   */\r\n  createElement(name, attributes = {}) {\r\n    return createSVGElement(name, {\r\n      \"stroke-width\": null,\r\n      stroke: this.settings.stroke,\r\n      fill: this.settings.fill,\r\n      style: {\r\n        \"stroke-width\": null,\r\n        stroke: null,\r\n        fill: null\r\n      },\r\n      ...attributes\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Create and append to the workspace an SVG element with default properties.\r\n   *\r\n   * @param {string} name\r\n   * @param {object} [attributes={}]\r\n   *\r\n   * @return {SVGElement}\r\n   */\r\n  append(name, attributes = {}) {\r\n    const element = this.createElement(name, attributes);\r\n    this.elements.bbox.appendChild(element);\r\n    return element;\r\n  }\r\n\r\n  /**\r\n   * Remove an element from the workspace.\r\n   *\r\n   * @param {string|Element} element Query selector string or an SVG Element.\r\n   */\r\n  remove(element) {\r\n    if (typeof element === \"string\") {\r\n      element = this.elements.bbox.querySelector(element);\r\n    }\r\n    this.elements.bbox.removeChild(element);\r\n  }\r\n}\r\n\r\nexport default Blueprint;\r\n","/**\r\n * Simple string tag replacement.\r\n *\r\n * ex.: format(\"Hello {{name}}\", { name: \"World\"}) // Hello World\r\n *\r\n * @param {string} string\r\n * @param {object} data\r\n *\r\n * @return {string}\r\n */\r\nfunction format(string, data) {\r\n  return string.replace(/(\\{\\{([^}]+)\\}\\})/g, function(match, p1, p2) {\r\n    return data[p2] || p1;\r\n  });\r\n}\r\n\r\n/**\r\n * Get an HTML string and return a collection of DOM Element.\r\n *\r\n * Only elements with a [data-key] attribute will be returned.\r\n *\r\n * ex.: toElements('<div data-key=\"myElement\">...</div>')\r\n * return: { myElement: Element }\r\n *\r\n * @param {string} string\r\n *\r\n * @return {object}\r\n */\r\nfunction toElements(string) {\r\n  const elements = {};\r\n\r\n  const div = document.createElement(\"div\");\r\n  div.innerHTML = string.trim();\r\n\r\n  const list = div.querySelectorAll(\"[data-key]\");\r\n\r\n  Array.prototype.forEach.call(list, function(item) {\r\n    elements[item.getAttribute(\"data-key\")] = item;\r\n  });\r\n\r\n  return elements;\r\n}\r\n\r\n/**\r\n * Get an HTML string and some data and return a collection of DOM Element.\r\n *\r\n * Only elements with a [data-key] attribute will be returned.\r\n *\r\n * ex.: template(\r\n *        '<div data-key=\"myElement\">{{message}}</div>',\r\n *        { message: \"Hello World\"}\r\n *      )\r\n * return: { myElement: Element }\r\n *\r\n * @param {string}      string\r\n * @param {null|object} [data=null]\r\n *\r\n * @return {object}\r\n */\r\nfunction template(string, data = null) {\r\n  return toElements(data ? format(string, data) : string);\r\n}\r\n\r\n/**\r\n * Create and return a template function from an HTML string.\r\n *\r\n * ex.: const myTemplate = templateFactory('<div data-key=\"myElement\">{{message}}</div>')\r\n *      myTemplate({ message: 'Hello World'}) // { myElement: Element }\r\n *\r\n * @param {string} string\r\n *\r\n * @return {Function}\r\n */\r\nfunction templateFactory(string) {\r\n  return function(data) {\r\n    return template(string, data);\r\n  };\r\n}\r\n\r\nexport { format, toElements, template, templateFactory };\r\nexport default template;\r\n","import { templateFactory } from \"../template\";\r\n\r\nexport default templateFactory(`\r\n<div data-key=\"blueprint\" class=\"{{className}} {{className}}-{{uid}}\" style=\"position: relative; width: {{width}}; height: {{height}};\">\r\n\r\n  <svg data-key=\"canvas\" class=\"{{className}}-grid\" style=\"position: relative; width: 100%; height: 100%; overflow: hidden;\" xmlns=\"http://www.w3.org/2000/svg\">\r\n\r\n    <defs>\r\n      <pattern id=\"gridPattern10\" width=\"0.1\" height=\"0.1\">\r\n        <path data-key=\"gridPattern10\" d=\"M 10 0 L 0 0 0 10\" fill=\"none\" stroke=\"{{gridColor}}\" stroke-width=\"0.1\" />\r\n      </pattern>\r\n      <pattern id=\"gridPattern100\" width=\"1\" height=\"1\">\r\n        <path data-key=\"gridPattern100\" d=\"M 100 0 L 0 0 0 100\" fill=\"none\" stroke=\"{{gridColor}}\" stroke-width=\"1\" />\r\n      </pattern>\r\n      <pattern data-key=\"gridPattern\" id=\"gridPattern\" width=\"100\" height=\"100\" patternUnits=\"userSpaceOnUse\">\r\n        <rect data-key=\"gridFill10\" fill=\"url(#gridPattern10)\" width=\"100\" height=\"100\" />\r\n        <rect data-key=\"gridFill100\" fill=\"url(#gridPattern100)\" width=\"100\" height=\"100\" opacity=\"{{gridOpacity}}\" />\r\n      </pattern>\r\n    </defs>\r\n\r\n    <rect data-key=\"background\" class=\"{{className}}-background\" width=\"100%\" height=\"100%\" fill=\"{{backgroundColor}}\" />\r\n    <rect data-key=\"grid\" class=\"{{className}}-grid\" width=\"100%\" height=\"100%\" fill=\"url(#gridPattern)\" />\r\n\r\n    <g data-key=\"axis\" class=\"{{className}}-axis\" style=\"opacity: {{axisOpacity}};\">\r\n      <line data-key=\"axisX\" x1=\"0\" y1=\"0\" x2=\"100%\" y2=\"0\" stroke=\"{{axisColor}}\" stroke-width=\"1\" transform=\"translate(0 0)\" />\r\n      <line data-key=\"axisY\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"100%\" stroke=\"{{axisColor}}\" stroke-width=\"1\" transform=\"translate(0 0)\" />\r\n    </g>\r\n\r\n    <g data-key=\"cursor\" class=\"{{className}}-cursor\" style=\"opacity: {{cursorOpacity}}; display: none;\">\r\n      <line data-key=\"cursorX\" x1=\"0\" y1=\"0\" x2=\"100%\" y2=\"0\" stroke=\"{{cursorColor}}\" stroke-width=\"1\" transform=\"translate(0 0)\" />\r\n      <line data-key=\"cursorY\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"100%\" stroke=\"{{cursorColor}}\" stroke-width=\"1\" transform=\"translate(0 0)\" />\r\n    </g>\r\n\r\n    <svg\r\n      data-key=\"workspace\"\r\n      class=\"{{className}}-workspace\"\r\n      width=\"1\"\r\n      height=\"1\"\r\n      viewBox=\"0 0 1 1\"\r\n      style=\"position: absolute; overflow: visible; fill: {{fill}}; stroke: {{stroke}}; stroke-width: {{strokeWidth}};\"\r\n      xmlns=\"http://www.w3.org/2000/svg\">\r\n      <g data-key=\"bbox\"></g>\r\n    </svg>\r\n\r\n  </svg>\r\n\r\n  <div\r\n    data-key=\"statusbar\"\r\n    class=\"{{className}}-statusbar\"\r\n    style=\"position: absolute;\">\r\n    <span data-key=\"position\">x: 0, y: 0</span> | zoom: <span data-key=\"zoom\">100 %</span>\r\n  </div>\r\n\r\n</div>\r\n`);\r\n"],"names":["const","settings","width","height","parentElement","parentSelector","className","backgroundColor","gridColor","gridOpacity","cursorColor","cursorOpacity","axisColor","axisOpacity","nonScalingStroke","strokeWidth","zoomFactor","zoomDirection","zoomLimit","min","max","fitPadding","stroke","fill","statusbarStyle","left","bottom","padding","color","Point","constructor","x","y","Array","isArray","undefined","parseFloat","add","point","p1","this","sub","mult","div","neg","distance","diff","Math","sqrt","midpoint","toArray","clone","xmlns","supportsPassiveEventListener","opts","Object","defineProperty","get","window","addEventListener","removeEventListener","e","addPassiveEventListener","element","name","callback","capture","passive","names","trim","split","forEach","addEvent","keys","let","key","setStyle","value","style","removeProperty","setProperty","setTransform","type","transform","getAttribute","types","replace","RegExp","join","setAttribute","removeAttribute","Pointer","pointerEvent","event","id","pointerId","position","movement","down","downTime","upTime","tapCount","tapDuration","panning","panDistance","panStartPosition","panOffsets","pinch","pinchRatio","pinchDistance","pinchMidpoint","pinchOffset","primary","panThreshold","tapThreshold","tapTimeout","eventTypes","Pointers","target","options","callbacks","pointers","Map","wheelTimeout","trackPointer","deletePointer","mouseEvent","onMouseWheel","hasPointer","has","getPointer","setPointer","pointer","set","delete","getPosition","offsets","getBoundingClientRect","pageX","pageY","top","tapRecognizer","eventType","clearTimeout","emit","setTimeout","panRecognizer","indexOf","onPinch","p2","assign","pinchRecognizer","p","pinchReset","isPrimary","Date","now","delta","deltaY","on","func","push","data","uid","isFirefox","navigator","userAgent","match","Blueprint","parent","ref","Element","Error","document","querySelector","getParent","elements","string","createElement","innerHTML","list","querySelectorAll","prototype","call","item","toElements","format","template","cursor","cursorCoords","scale","gridSize","appendChild","blueprint","statusbar","getRelativePosition","redrawStatusbar","fit","panId","pan","updateCursorPosition","hide","zoom","ratio","show","what","display","round","decimals","toString","length","toFixed","innerText","redraw","axisX","axisY","cursorX","cursorY","gridPattern","gridPath","gridFill10","gridFill100","gridPattern10","gridPattern100","workspace","cloneNode","canvas","replaceChild","bbox","move","getWorkspaceCenter","offsetWidth","offsetHeight","oldScale","coords","center","attributes","mimeType","charAt","DOMParser","parseFromString","documentElement","firstChild","createElementNS","createSVGElement","append","remove","removeChild"],"mappings":"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"}