(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports);
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports);
    global.flowModule = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.Utils = _exports.ToggleInput = _exports.TitleElement = _exports.TextInput = _exports.StringInput = _exports.SliderInput = _exports.Serializer = _exports.SelectInput = _exports.REVISION = _exports.PanelNode = _exports.ObjectNode = _exports.NumberInput = _exports.Node = _exports.Menu = _exports.Loader = _exports.LabelElement = _exports.Input = _exports.Element = _exports.DraggableElement = _exports.ContextMenu = _exports.ColorInput = _exports.CircleMenu = _exports.Canvas = _exports.ButtonInput = void 0;

  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

  function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }

  function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }

  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }

  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }

  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }

  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }

  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }

  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

  function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

  function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }

  function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }

  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

  function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }

  function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

  /**
   * https://github.com/sunag/flow
   */
  function __flow__addCSS(css) {
    try {
      var style = document.createElement('style');
      style.setAttribute('type', 'text/css');
      style.innerHTML = css;
      document.head.appendChild(style);
    } catch (e) {}
  }

  __flow__addCSS("f-canvas,f-canvas canvas { position: absolute; top: 0; left: 0; margin: 0; padding: 0; width: 100%; height: 100%; -webkit-touch-callout: none; }f-canvas { overflow: auto; cursor: grab;}f-canvas canvas.front { z-index: 10;}body.dragging f-canvas,body.connecting f-canvas { overflow: hidden !important;}body.dragging *:not(.drag) { pointer-events: none !important;}f-canvas.grabbing * { cursor: grabbing; user-select: none;}f-canvas canvas { position: fixed; overflow: hidden; pointer-events: none;}f-canvas::-webkit-scrollbar { width: 8px; height: 8px;}f-canvas::-webkit-scrollbar-thumb:hover{ background: #014fc5;}f-canvas::-webkit-scrollbar-track { background: #363636;}f-canvas::-webkit-scrollbar-thumb { background-color: #666666; border-radius: 10px; border: 0;}f-canvas f-content,f-canvas f-area { position: absolute; display: block;}f-node { position: absolute; margin: 0; padding: 0; user-select: none; width: 320px; z-index: 1; cursor: auto; filter: drop-shadow(0 0 10px #00000061); backdrop-filter: blur(4px);}f-node.selected { z-index: 2;}f-node.selected,f-canvas.dragging-rio f-node:hover,f-canvas.dragging-lio f-node:hover { filter: drop-shadow(0 0 10px #00000061) drop-shadow(0 0 8px #4444dd);}f-node.closed f-element:not(:first-child) { display: none;}f-node.center { top: 50%; left: 50%; transform: translate( -50%, -50% );}f-node.top-right { top: 0; right: 0;}f-node.top-center { top: 0; left: 50%; transform: translateX( -50% );}f-node.top-left { top: 0; left: 0;}f-node { transition: filter 0.2s ease;}@keyframes f-open { 0% { transform: scale(.5); filter: blur(30px); } 100% { transform: scale(1); filter: unset }}f-node { animation: .2s f-open 1 alternate ease-out;}f-menu,f-menu button,f-element,f-element input,f-element select,f-element button,f-element textarea { font-family: 'Open Sans', sans-serif; font-size: 13px; text-transform: capitalize; color: #eeeeee; outline: solid 0px #000; letter-spacing: .2px; margin: 0; padding: 0; border: 0; user-select: none; -webkit-tap-highlight-color: transparent; transition: background 0.2s ease;}f-element input { transition: background 0.1s ease;}f-element input,f-element select,f-element button,f-element textarea { background-color: #242427;}f-element { position: relative; width: calc( 100% - 14px ); background: rgba(45, 45, 48, 0.95); pointer-events: auto; border-bottom: 2px solid #232323; display: flex; padding-left: 7px; padding-right: 7px; padding-top: 2px; padding-bottom: 2px;}f-element { height: 24px;}f-element input { margin-top: 2px; margin-bottom: 2px; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%); margin-left: 2px; margin-right: 2px; width: 100%; padding-left: 4px; padding-right: 4px;}f-element input.number { cursor: col-resize;}f-element input:focus[type='text'], f-element input:focus[type='range'], f-element input:focus[type='color'] { background: rgba( 0, 0, 0, 0.6 ); outline: solid 1px rgba( 0, 80, 200, 0.98 );}f-element input[type='color'] { appearance: none; padding: 0; margin-left: 2px; margin-right: 2px; height: calc( 100% - 4px ); margin-top: 2px; border: none; }f-element input[type='color']::-webkit-color-swatch-wrapper { padding: 2px;}f-element input[type='color']::-webkit-color-swatch { border: none; cursor: alias;}f-element input[type='range'] { appearance: none; width: 100%; overflow: hidden; padding: 0; cursor: ew-resize;}f-element input[type='range']::-webkit-slider-runnable-track { appearance: none; height: 10px; color: #13bba4; margin: 0;}f-element input[type='range']::-webkit-slider-thumb { appearance: none; width: 0; background: #434343; box-shadow: -500px 0 0 500px rgba( 0, 120, 255, 0.98 ); border-radius: 50%; border: 0 !important;}f-element input[type='range']::-webkit-slider-runnable-track { margin-left: -4px; margin-right: -5px;}f-element input[type='checkbox'] { appearance: none; cursor: pointer;}f-element input[type='checkbox'].toggle { height: 20px; width: 45px; border-radius: 16px; display: inline-block; position: relative; margin: 0; margin-top: 2px; background: linear-gradient( 0deg, #292929 0%, #0a0a0ac2 100% ); transition: all 0.2s ease;}f-element input[type='checkbox'].toggle:after { content: \"\"; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: white; box-shadow: 0 1px 2px rgba(44, 44, 44, 0.2); transition: all 0.2s cubic-bezier(0.5, 0.1, 0.75, 1.35);}f-element input[type='checkbox'].toggle:checked { background: linear-gradient( 0deg, #0177fb 0%, #0177fb 100% );}f-element input[type='checkbox'].toggle:checked:after { transform: translatex(25px);}f-element.auto-height { display: table;}f-element textarea { width: calc( 100% - 18px ); padding-top: 1px; padding-bottom: 3px; padding-left: 3px; padding-right: 8px; margin-top: 2px; margin-left: 2px; height: calc( 100% - 8px ); max-height: 300px; border-radius: 2px; resize: none; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%);}f-element.auto-height textarea { resize: auto;}f-element select { width: 100%; margin-top: 2px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; padding-left: 5px; cursor: pointer; box-shadow: inset 0px 1px 1px rgb(0 0 0 / 20%), 0px 1px 0px rgb(255 255 255 / 5%);}f-element f-toolbar { position: absolute; display: flex; top: 0; width: 100%; height: 100%; align-content: space-around;}f-element.output-right f-toolbar { right: 7px; float: right; justify-content: end;}f-element f-toolbar { margin-top: auto; margin-bottom: auto; margin-left: 3px; margin-right: 3px; font-size: 18px; line-height: 18px;}f-element f-toolbar button { opacity: .7; cursor: pointer; font-size: 14px; width: unset; height: unset; border-radius: unset; border: unset; outline: 0; background-color: unset; box-shadow: unset;}f-element f-toolbar button:hover,f-element f-toolbar button:active { opacity: 1; border: 0; background-color: unset;}f-element input.range-value { width: 60px; text-align: center;}f-menu.context button,f-element button { width: 100%; height: calc( 100% - 4px ); margin-left: 2px; margin-right: 2px; margin-top: 2px; border-radius: 3px; cursor: pointer;}f-element button { box-shadow: inset 1px 1px 1px 0 rgb(255 255 255 / 17%), inset -2px -2px 2px 0 rgb(0 0 0 / 26%);}f-element button:hover { color: #fff; background-color: #2a2a2a;}f-element button:active { border: 1px solid rgba( 0, 120, 255, 0.98 );}f-element f-inputs,f-element f-subinputs { display: flex; width: 100%;}f-element f-inputs { left: 100px; top: 50%; transform: translateY(-50%); position: absolute; width: calc( 100% - 106px ); height: calc( 100% - 4px ); z-index: 1;}f-element f-label,f-element span { margin: auto; text-shadow: 1px 1px 0px #0007;}f-element f-label { padding-left: 4px; white-space: nowrap; position: absolute; top: 50%; transform: translateY(-50%); width: calc( 100% - 20px );}f-element.right f-label { text-align: right;}f-element f-label i { float: left; font-size: 18px; margin-right: 6px;}f-element f-label.center { width: 100%; text-align: center; display: block;}f-element.title { height: 29px; background-color: #3a3a3ab0; background-color: #3b3b43ed; cursor: all-scroll; border-top-left-radius: 6px; border-top-right-radius: 6px;}f-element.blue { background-color: #014fc5;}f-element.red { background-color: #bd0b0b;}f-element.green { background-color: #148d05;}f-element.yellow { background-color: #d6b100;}f-element.title.left { text-align: left; display: inline-grid; justify-content: start;}f-element.title span { text-align: center; font-size: 15px; padding-top: 2px;}f-element.title i { font-size: 18px; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); opacity: .5;}f-element.output-right.title i { left: 10px; right: unset;}f-element.title.left span { text-align: left;}f-element f-io { border: 2px solid #dadada; width: 7px; height: 7px; position: absolute; background: #242427; border-radius: 8px; float: left; left: -7px; top: calc( 50% - 5px ); cursor: alias; box-shadow: 0 0 3px 2px #0000005e; z-index: 1;}f-element f-io.connect,f-canvas.dragging-rio f-element:hover f-io.lio,f-canvas.dragging-lio f-element:hover f-io.rio { border: 2px solid #0177fb; zoom: 1.4;}f-node.io-connect f-io:not(.connect) { border: 2px solid #dadada !important; zoom: 1 !important;}f-element f-io.rio { float: right; right: -7px; left: unset;}f-element f-disconnect { position: absolute; left: -35px; top: 50%; font-size: 22px; transform: translateY( -50% ); filter: drop-shadow(0 0 5px #000); text-shadow: 0px 0px 5px black; cursor: pointer;}f-element.output-right f-disconnect { right: -35px; left: unset;}f-element f-disconnect:hover { color: #ff3300;}f-element textarea::-webkit-scrollbar { width: 6px;}f-element textarea::-webkit-scrollbar-track { background: #111; } f-element textarea::-webkit-scrollbar-thumb { background: #0177fb; }f-element textarea::-webkit-scrollbar-thumb:hover { background: #1187ff; }f-element.small { height: 18px;}f-element.large { height: 36px;}body.connecting f-node:not(.io-connect) f-element:hover,f-element.select { background-color: rgba(61, 70, 82, 0.98);}f-tooltip { pointer-events: none;}f-tooltip { position: absolute; left: 0; top: 0; background: rgba(0,0,0,.8); backdrop-filter: blur(4px); font-size: 14px; padding: 7px; border-radius: 10px; top: 50%; transform: translateY(-50%); visibility: hidden; pointer-events: none; opacity: 0; transition: all 0.3s ease; z-index: 150; white-space: nowrap;}f-menu.context { position: absolute; width: 170px; padding: 2px; margin: 0; background: #17171794; z-index: 110; font-size: 12px; border-radius: 6px; backdrop-filter: blur(6px); border: 1px solid #7e7e7e45; box-shadow: 3px 3px 6px rgba(0,0,0,.2); transition: opacity 0.2s ease, transform 0.1s ease;}f-menu.context.hidden { visibility: hidden; opacity: 0;}f-menu.context f-item { display: block; position: relative; margin: 0; padding: 0; white-space: nowrap;}f-menu.context f-item.submenu::after { content: \"\"; position: absolute; right: 6px; top: 50%; -webkit-transform: translateY(-50%); transform: translateY(-50%); border: 5px solid transparent; border-left-color: #808080;}f-menu.context f-item:hover > f-menu,f-menu.context f-item.active > f-menu { visibility: unset; transform: unset; opacity: unset;}f-menu.context f-menu { top: 0px; left: calc( 100% - 4px );}f-menu.context f-item button { overflow: visible; display: block; width: calc( 100% - 6px ); text-align: left; cursor: pointer; white-space: nowrap; padding: 6px 8px; border-radius: 3px; background: #2d2d32; border: 0; color: #ddd; margin: 3px; text-shadow: 1px 1px 0px #0007;}f-menu.context f-item button i { float: left; font-size: 16px;}f-menu.context f-item button span { margin-left: 6px;}f-menu.context f-item:hover > button,f-menu.context f-item.active > button { color: #fff; background: #313136;}f-menu.context f-item button:active { outline: solid 1px rgba( 0, 80, 200, 0.98 );}f-menu.context f-item f-tooltip { margin-left: 120px;}f-menu.circle { position: absolute; left: 30px; top: 30px; z-index: 100;}f-menu.circle f-item { display: flex; justify-content: end; align-content: space-around; margin-bottom: 12px;}f-menu.circle f-item button { width: 50px; height: 50px; font-size: 26px; background: #17171794; border-radius: 50%; backdrop-filter: blur(6px); border: 1px solid #7e7e7e45; line-height: 100%; cursor: pointer; box-shadow: 3px 3px 6px rgba(0,0,0,.2);}f-menu.circle f-item f-tooltip { margin-left: 50px;}.f-rounded f-node f-element,.f-rounded f-node f-element.title.left { border-radius: 10px 5px 10px 5px;}.f-rounded f-node f-element input, .f-rounded f-node f-element select,.f-rounded f-node f-element button,.f-rounded f-node f-element textarea,.f-rounded f-node f-element input[type='checkbox'].toggle,.f-rounded f-node f-element input[type='checkbox'].toggle:after { border-radius: 20px 10px;}.f-rounded f-node f-element input { padding-left: 7px; padding-right: 7px;}.f-rounded f-menu.context,.f-rounded f-menu.context f-item button { border-radius: 20px 10px;}@media (hover: hover) and (pointer: fine) { f-element f-io:hover { border: 2px solid #0177fb; zoom: 1.4; } f-menu.circle f-item button:hover { background-color: #2a2a2a; } f-menu.circle f-item button:hover > f-tooltip, f-menu.context f-item button:hover > f-tooltip { visibility: visible; transform: translate(10px, -50%); opacity: 1; } f-menu.circle f-item button:focus > f-tooltip, f-menu.context f-item button:focus > f-tooltip { visibility: hidden; opacity: 0; }}f-canvas { will-change: top, left;}f-node { will-change: transform !important;}");

  var REVISION = '1';
  _exports.REVISION = REVISION;
  var _id = 0;

  var Serializer = /*#__PURE__*/function (_EventTarget) {
    _inherits(Serializer, _EventTarget);

    var _super = _createSuper(Serializer);

    function Serializer() {
      var _this;

      _classCallCheck(this, Serializer);

      _this = _super.call(this);
      _this._id = _id++;
      _this._serializable = true;
      return _this;
    }

    _createClass(Serializer, [{
      key: "id",
      get: function get() {
        return this._id;
      }
    }, {
      key: "setSerializable",
      value: function setSerializable(value) {
        this._serializable = value;
        return this;
      }
    }, {
      key: "getSerializable",
      value: function getSerializable() {
        return this._serializable;
      }
    }, {
      key: "serialize",
      value: function
        /*data*/
      serialize() {
        console.warn('Serializer: Abstract function.');
      }
    }, {
      key: "deserialize",
      value: function
        /*data*/
      deserialize() {
        console.warn('Serializer: Abstract function.');
      }
    }, {
      key: "toJSON",
      value: function toJSON() {
        var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
        var object = null;
        var id = this.id;

        if (data !== null) {
          var objects = data.objects;
          object = objects[id];

          if (object === undefined) {
            object = {
              objects: objects
            };
            this.serialize(object);
            delete object.objects;
            objects[id] = object;
          }
        } else {
          object = {
            objects: {}
          };
          this.serialize(object);
        }

        object.id = id;
        object.type = this.constructor.name;
        return object;
      }
    }]);

    return Serializer;
  }( /*#__PURE__*/_wrapNativeSuper(EventTarget));

  _exports.Serializer = Serializer;

  var draggableDOM = function draggableDOM(dom) {
    var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
    var className = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'dragging';
    var dragData = null;

    var getZoom = function getZoom() {
      var zoomDOM = dom;

      while (zoomDOM && zoomDOM !== document) {
        var zoom = zoomDOM.style.zoom;

        if (zoom) {
          return Number(zoom);
        }

        zoomDOM = zoomDOM.parentNode;
      }

      return 1;
    };

    var onMouseDown = function onMouseDown(e) {
      var event = e.touches ? e.touches[0] : e;
      e.stopImmediatePropagation();
      dragData = {
        client: {
          x: event.clientX,
          y: event.clientY
        },
        delta: {
          x: 0,
          y: 0
        },
        start: {
          x: dom.offsetLeft,
          y: dom.offsetTop
        },
        dragging: false,
        isTouch: !!e.touches
      };
      window.addEventListener('mousemove', onGlobalMouseMove);
      window.addEventListener('mouseup', onGlobalMouseUp);
      window.addEventListener('touchmove', onGlobalMouseMove);
      window.addEventListener('touchend', onGlobalMouseUp);
    };

    var onGlobalMouseMove = function onGlobalMouseMove(e) {
      var _dragData = dragData,
          start = _dragData.start,
          delta = _dragData.delta,
          client = _dragData.client;
      var event = e.touches ? e.touches[0] : e;
      var zoom = getZoom();
      delta.x = (event.clientX - client.x) / zoom;
      delta.y = (event.clientY - client.y) / zoom;
      dragData.x = start.x + delta.x;
      dragData.y = start.y + delta.y;

      if (dragData.dragging === true) {
        if (callback !== null) {
          callback(dragData);
        } else {
          dom.style.cssText += "; left: ".concat(dragData.x, "px; top: ").concat(dragData.y, "px;");
        }

        e.stopImmediatePropagation();
      } else {
        if (Math.abs(delta.x) > 2 || Math.abs(delta.y) > 2) {
          dragData.dragging = true;
          dom.classList.add('drag');
          if (className) document.body.classList.add(className);
          e.stopImmediatePropagation();
        }
      }
    };

    var onGlobalMouseUp = function onGlobalMouseUp(e) {
      e.stopImmediatePropagation();
      dom.classList.remove('drag');
      if (className) document.body.classList.remove(className);
      window.removeEventListener('mousemove', onGlobalMouseMove);
      window.removeEventListener('mouseup', onGlobalMouseUp);
      window.removeEventListener('touchmove', onGlobalMouseMove);
      window.removeEventListener('touchend', onGlobalMouseUp);

      if (callback === null) {
        dom.removeEventListener('mousedown', onMouseDown);
        dom.removeEventListener('touchstart', onMouseDown);
      }

      dragData.dragging = false;

      if (callback !== null) {
        callback(dragData);
      }
    };

    if (dom instanceof Event) {
      var e = dom;
      dom = e.target;
      onMouseDown(e);
    } else {
      dom.addEventListener('mousedown', onMouseDown);
      dom.addEventListener('touchstart', onMouseDown);
    }
  };

  var dispatchEventList = function dispatchEventList(list) {
    for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      params[_key - 1] = arguments[_key];
    }

    var _iterator = _createForOfIteratorHelper(list),
        _step;

    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var callback = _step.value;
        callback.apply(void 0, params);
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
  };

  var toPX = function toPX(val) {
    if (isNaN(val) === false) {
      val = "".concat(val, "px");
    }

    return val;
  };

  var toHex = function toHex(val) {
    if (isNaN(val) === false) {
      val = "#".concat(val.toString(16).padStart(6, '0'));
    }

    return val;
  };

  var Utils = /*#__PURE__*/Object.freeze({
    __proto__: null,
    draggableDOM: draggableDOM,
    dispatchEventList: dispatchEventList,
    toPX: toPX,
    toHex: toHex
  });
  _exports.Utils = Utils;

  var Link = /*#__PURE__*/function () {
    function Link() {
      var inputElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
      var outputElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

      _classCallCheck(this, Link);

      this.inputElement = inputElement;
      this.outputElement = outputElement;
    }

    _createClass(Link, [{
      key: "lioElement",
      get: function get() {
        if (Link.InputDirection === 'left') {
          return this.outputElement;
        } else {
          return this.inputElement;
        }
      }
    }, {
      key: "rioElement",
      get: function get() {
        if (Link.InputDirection === 'left') {
          return this.inputElement;
        } else {
          return this.outputElement;
        }
      }
    }]);

    return Link;
  }(); //Link.InputDirection = 'right';


  Link.InputDirection = 'left';
  var selected = null;

  var Element = /*#__PURE__*/function (_Serializer) {
    _inherits(Element, _Serializer);

    var _super2 = _createSuper(Element);

    function Element() {
      var _this2;

      var draggable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      _classCallCheck(this, Element);

      _this2 = _super2.call(this);
      var dom = document.createElement('f-element');
      dom.element = _assertThisInitialized(_this2);

      var onSelect = function onSelect(e) {
        var element = _assertThisInitialized(_this2);

        if (e.changedTouches && e.changedTouches.length > 0) {
          var touch = e.changedTouches[0];
          var overDOM = document.elementFromPoint(touch.clientX, touch.clientY);

          while (overDOM && (!overDOM.element || !overDOM.element.isElement)) {
            overDOM = overDOM.parentNode;
          }

          element = overDOM ? overDOM.element : null;
        }

        selected = element;
      };

      if (draggable === false) {
        dom.ontouchstart = dom.onmousedown = function (e) {
          e.stopPropagation();
        };
      }

      dom.addEventListener('mouseup', onSelect, true);
      dom.addEventListener('touchend', onSelect);
      _this2.inputs = [];
      _this2.links = [];
      _this2.dom = dom;
      _this2.lioLength = 0;
      _this2.rioLength = 0;
      _this2.events = {
        'connect': [],
        'connectChildren': []
      };
      _this2.node = null;
      _this2.style = '';
      _this2.extra = null;
      _this2.visible = true;
      _this2.inputsDOM = dom;
      _this2.disconnectDOM = null;
      _this2.lioDOM = _this2._createIO('lio');
      _this2.rioDOM = _this2._createIO('rio');

      _this2.dom.classList.add("output-".concat(Link.InputDirection));

      _this2.dom.appendChild(_this2.lioDOM);

      _this2.dom.appendChild(_this2.rioDOM);

      _this2.addEventListener('connect', function () {
        dispatchEventList(_this2.events.connect, _assertThisInitialized(_this2));
      });

      _this2.addEventListener('connectChildren', function () {
        dispatchEventList(_this2.events.connectChildren, _assertThisInitialized(_this2));
      });

      return _this2;
    }

    _createClass(Element, [{
      key: "onConnect",
      value: function onConnect(callback) {
        var childrens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
        this.events.connect.push(callback);

        if (childrens) {
          this.events.connectChildren.push(callback);
        }

        return this;
      }
    }, {
      key: "setExtra",
      value: function setExtra(value) {
        this.extra = value;
        return this;
      }
    }, {
      key: "getExtra",
      value: function getExtra() {
        return this.extra;
      }
    }, {
      key: "setVisible",
      value: function setVisible(value) {
        this.visible = value;
        this.dom.style.display = value ? '' : 'none';
        return this;
      }
    }, {
      key: "getVisible",
      value: function getVisible() {
        return this.visible;
      }
    }, {
      key: "setStyle",
      value: function setStyle(style) {
        var dom = this.dom;
        if (this.style) dom.classList.remove(this.style);
        if (style) dom.classList.add(style);
        this.style = style;
        return this;
      }
    }, {
      key: "setInput",
      value: function setInput(length) {
        if (Link.InputDirection === 'left') {
          return this.setLIO(length);
        } else {
          return this.setRIO(length);
        }
      }
    }, {
      key: "setOutput",
      value: function setOutput(length) {
        if (Link.InputDirection === 'left') {
          return this.setRIO(length);
        } else {
          return this.setLIO(length);
        }
      }
    }, {
      key: "inputLength",
      get: function get() {
        if (Link.InputDirection === 'left') {
          return this.lioLength;
        } else {
          return this.rioLength;
        }
      }
    }, {
      key: "outputLength",
      get: function get() {
        if (Link.InputDirection === 'left') {
          return this.rioLength;
        } else {
          return this.lioLength;
        }
      }
    }, {
      key: "setLIO",
      value: function setLIO(length) {
        this.lioLength = length;
        this.lioDOM.style.visibility = length > 0 ? '' : 'hidden';
        return this;
      }
    }, {
      key: "setRIO",
      value: function setRIO(length) {
        this.rioLength = length;
        this.rioDOM.style.visibility = length > 0 ? '' : 'hidden';
        return this;
      }
    }, {
      key: "add",
      value: function add(input) {
        this.inputs.push(input);
        input.element = this;
        this.inputsDOM.appendChild(input.dom);
        return this;
      }
    }, {
      key: "setHeight",
      value: function setHeight(val) {
        this.dom.style.height = toPX(val);
        return this;
      }
    }, {
      key: "getHeight",
      value: function getHeight() {
        return this.dom.style.height;
      }
    }, {
      key: "connect",
      value: function connect() {
        var _this3 = this;

        var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

        if (this.disconnectDOM !== null) {
          // remove the current input
          this.disconnectDOM.dispatchEvent(new Event('disconnect'));
        }

        if (element !== null) {
          var link = new Link(this, element);
          this.links.push(link);

          if (this.disconnectDOM === null) {
            this.disconnectDOM = document.createElement('f-disconnect');
            this.disconnectDOM.innerText = '✖';
            this.dom.appendChild(this.disconnectDOM);

            var onDisconnect = function onDisconnect() {
              _this3.links = [];

              _this3.dom.removeChild(_this3.disconnectDOM);

              _this3.disconnectDOM.removeEventListener('mousedown', onClick, true);

              _this3.disconnectDOM.removeEventListener('touchstart', onClick, true);

              _this3.disconnectDOM.removeEventListener('disconnect', onDisconnect, true);

              element.removeEventListener('connect', onConnect);
              element.removeEventListener('connectChildren', onConnect);
              element.removeEventListener('nodeConnect', onConnect);
              element.removeEventListener('nodeConnectChildren', onConnect);
              element.removeEventListener('dispose', onDispose);
              _this3.disconnectDOM = null;
            };

            var onConnect = function onConnect(e) {
              _this3.dispatchEvent(new Event('connectChildren'));
            };

            var onDispose = function onDispose() {
              _this3.connect();
            };

            var onClick = function onClick(e) {
              e.stopPropagation();

              _this3.connect();
            };

            this.disconnectDOM.addEventListener('mousedown', onClick, true);
            this.disconnectDOM.addEventListener('touchstart', onClick, true);
            this.disconnectDOM.addEventListener('disconnect', onDisconnect, true);
            element.addEventListener('connect', onConnect);
            element.addEventListener('connectChildren', onConnect);
            element.addEventListener('nodeConnect', onConnect);
            element.addEventListener('nodeConnectChildren', onConnect);
            element.addEventListener('dispose', onDispose);
          }
        }

        this.dispatchEvent(new Event('connect'));
        return this;
      }
    }, {
      key: "dispose",
      value: function dispose() {
        this.dispatchEvent(new Event('dispose'));
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        var height = this.getHeight();
        var inputs = [];
        var links = [];

        var _iterator2 = _createForOfIteratorHelper(this.inputs),
            _step2;

        try {
          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
            var input = _step2.value;
            inputs.push(input.toJSON(data).id);
          }
        } catch (err) {
          _iterator2.e(err);
        } finally {
          _iterator2.f();
        }

        var _iterator3 = _createForOfIteratorHelper(this.links),
            _step3;

        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var link = _step3.value;

            if (link.inputElement !== null && link.outputElement !== null) {
              links.push(link.outputElement.toJSON(data).id);
            }
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }

        if (this.inputLength > 0) data.inputLength = this.inputLength;
        if (this.outputLength > 0) data.outputLength = this.outputLength;
        if (inputs.length > 0) data.inputs = inputs;
        if (links.length > 0) data.links = links;

        if (this.style !== '') {
          data.style = this.style;
        }

        if (height !== '') {
          data.height = height;
        }
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        if (data.inputLength !== undefined) this.setInput(data.inputLength);
        if (data.outputLength !== undefined) this.setOutput(data.outputLength);

        if (data.inputs !== undefined) {
          var inputs = this.inputs;

          if (inputs.length > 0) {
            var index = 0;

            var _iterator4 = _createForOfIteratorHelper(data.inputs),
                _step4;

            try {
              for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
                var id = _step4.value;
                data.objects[id] = inputs[index++];
              }
            } catch (err) {
              _iterator4.e(err);
            } finally {
              _iterator4.f();
            }
          } else {
            var _iterator5 = _createForOfIteratorHelper(data.inputs),
                _step5;

            try {
              for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
                var _id2 = _step5.value;
                this.add(data.objects[_id2]);
              }
            } catch (err) {
              _iterator5.e(err);
            } finally {
              _iterator5.f();
            }
          }
        }

        if (data.links !== undefined) {
          var _iterator6 = _createForOfIteratorHelper(data.links),
              _step6;

          try {
            for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
              var _id3 = _step6.value;
              this.connect(data.objects[_id3]);
            }
          } catch (err) {
            _iterator6.e(err);
          } finally {
            _iterator6.f();
          }
        }

        if (data.style !== undefined) {
          this.setStyle(data.style);
        }

        if (data.height !== undefined) {
          this.setHeight(data.height);
        }
      }
    }, {
      key: "linkedExtra",
      get: function get() {
        var linkedElement = this.linkedElement;
        return linkedElement ? linkedElement.getExtra() : null;
      }
    }, {
      key: "linkedElement",
      get: function get() {
        var link = this.link;
        return link ? link.outputElement : null;
      }
    }, {
      key: "link",
      get: function get() {
        return this.links[0];
      }
    }, {
      key: "_createIO",
      value: function _createIO(type) {
        var _this4 = this;

        var dom = this.dom;
        var ioDOM = document.createElement('f-io');
        ioDOM.style.visibility = 'hidden';
        ioDOM.className = type;

        var onConnectEvent = function onConnectEvent(e) {
          e.preventDefault();
          e.stopPropagation();
          selected = null;
          var nodeDOM = _this4.node.dom;
          nodeDOM.classList.add('io-connect');
          ioDOM.classList.add('connect');
          dom.classList.add('select');
          var defaultOutput = Link.InputDirection === 'left' ? 'lio' : 'rio';
          var link = type === defaultOutput ? new Link(_this4) : new Link(null, _this4);

          _this4.links.push(link);

          draggableDOM(e, function (data) {
            if (data.dragging === false) {
              nodeDOM.classList.remove('io-connect');
              ioDOM.classList.remove('connect');
              dom.classList.remove('select');

              _this4.links.splice(_this4.links.indexOf(link), 1);

              if (selected !== null) {
                if (type === defaultOutput) {
                  link.outputElement = selected;
                } else {
                  link.inputElement = selected;
                } // check if is an is circular link


                if (link.outputElement.node.isCircular(link.inputElement.node)) {
                  return;
                } //


                if (link.inputElement.inputLength > 0 && link.outputElement.outputLength > 0) {
                  link.inputElement.connect(link.outputElement);
                }
              }
            }
          }, 'connecting');
        };

        ioDOM.addEventListener('mousedown', onConnectEvent, true);
        ioDOM.addEventListener('touchstart', onConnectEvent, true);
        return ioDOM;
      }
    }]);

    return Element;
  }(Serializer);

  _exports.Element = Element;
  Element.prototype.isElement = true;

  var Input = /*#__PURE__*/function (_Serializer2) {
    _inherits(Input, _Serializer2);

    var _super3 = _createSuper(Input);

    function Input(dom) {
      var _this5;

      _classCallCheck(this, Input);

      _this5 = _super3.call(this);
      _this5.dom = dom;
      _this5.element = null;
      _this5.extra = null;
      _this5.events = {
        'change': [],
        'click': []
      };

      _this5.addEventListener('change', function () {
        dispatchEventList(_this5.events.change, _assertThisInitialized(_this5));
      });

      _this5.addEventListener('click', function () {
        dispatchEventList(_this5.events.click, _assertThisInitialized(_this5));
      });

      return _this5;
    }

    _createClass(Input, [{
      key: "setExtra",
      value: function setExtra(value) {
        this.extra = value;
        return this;
      }
    }, {
      key: "getExtra",
      value: function getExtra() {
        return this.extra;
      }
    }, {
      key: "setToolTip",
      value: function setToolTip(text) {
        var div = document.createElement('f-tooltip');
        div.innerText = text;
        this.dom.appendChild(div);
        return this;
      }
    }, {
      key: "onChange",
      value: function onChange(callback) {
        this.events.change.push(callback);
        return this;
      }
    }, {
      key: "onClick",
      value: function onClick(callback) {
        this.events.click.push(callback);
        return this;
      }
    }, {
      key: "setValue",
      value: function setValue(value) {
        var dispatch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
        this.dom.value = value;
        if (dispatch) this.dispatchEvent(new Event('change'));
        return this;
      }
    }, {
      key: "getValue",
      value: function getValue() {
        return this.dom.value;
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        data.value = this.getValue();
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        this.setValue(data.value);
      }
    }]);

    return Input;
  }(Serializer);

  _exports.Input = Input;
  Input.prototype.isInput = true;

  var Node = /*#__PURE__*/function (_Serializer3) {
    _inherits(Node, _Serializer3);

    var _super4 = _createSuper(Node);

    function Node() {
      var _this6;

      _classCallCheck(this, Node);

      _this6 = _super4.call(this);
      var dom = document.createElement('f-node');

      var onDown = function onDown() {
        var canvas = _this6.canvas;

        if (canvas !== null) {
          canvas.select(_assertThisInitialized(_this6));
        }
      };

      dom.addEventListener('mousedown', onDown, true);
      dom.addEventListener('touchstart', onDown, true);

      _this6._onConnect = function (e) {
        var target = e.target;

        var _iterator7 = _createForOfIteratorHelper(_this6.elements),
            _step7;

        try {
          for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
            var element = _step7.value;

            if (element !== target) {
              element.dispatchEvent(new Event('nodeConnect'));
            }
          }
        } catch (err) {
          _iterator7.e(err);
        } finally {
          _iterator7.f();
        }
      };

      _this6._onConnectChildren = function (e) {
        var target = e.target;

        var _iterator8 = _createForOfIteratorHelper(_this6.elements),
            _step8;

        try {
          for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
            var element = _step8.value;

            if (element !== target) {
              element.dispatchEvent(new Event('nodeConnectChildren'));
            }
          }
        } catch (err) {
          _iterator8.e(err);
        } finally {
          _iterator8.f();
        }
      };

      _this6.dom = dom;
      _this6.style = '';
      _this6.canvas = null;
      _this6.elements = [];
      _this6.events = {
        'focus': [],
        'blur': []
      };

      _this6.setPosition(0, 0);

      return _this6;
    }

    _createClass(Node, [{
      key: "onFocus",
      value: function onFocus(callback) {
        this.events.focus.push(callback);
        return this;
      }
    }, {
      key: "onBlur",
      value: function onBlur(callback) {
        this.events.blur.push(callback);
        return this;
      }
    }, {
      key: "setStyle",
      value: function setStyle(style) {
        var dom = this.dom;
        if (this.style) dom.classList.remove(this.style);
        if (style) dom.classList.add(style);
        this.style = style;
        return this;
      }
    }, {
      key: "setPosition",
      value: function setPosition(x, y) {
        var dom = this.dom;
        dom.style.left = toPX(x);
        dom.style.top = toPX(y);
        return this;
      }
    }, {
      key: "getPosition",
      value: function getPosition() {
        var dom = this.dom;
        return {
          x: parseInt(dom.style.left),
          y: parseInt(dom.style.top)
        };
      }
    }, {
      key: "setWidth",
      value: function setWidth(val) {
        this.dom.style.width = toPX(val);
        return this;
      }
    }, {
      key: "getWidth",
      value: function getWidth() {
        return this.dom.style.width;
      }
    }, {
      key: "add",
      value: function add(element) {
        this.elements.push(element);
        element.node = this;
        element.addEventListener('connect', this._onConnect);
        element.addEventListener('connectChildren', this._onConnectChildren);
        this.dom.appendChild(element.dom);
        return this;
      }
    }, {
      key: "remove",
      value: function remove(element) {
        this.elements.splice(this.elements.indexOf(element), 1);
        element.node = null;
        element.removeEventListener('connect', this._onConnect);
        element.removeEventListener('connectChildren', this._onConnectChildren);
        this.dom.removeChild(element.dom);
        return this;
      }
    }, {
      key: "dispose",
      value: function dispose() {
        var canvas = this.canvas;
        if (canvas !== null) canvas.remove(this);

        var _iterator9 = _createForOfIteratorHelper(this.elements),
            _step9;

        try {
          for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
            var element = _step9.value;
            element.dispose();
          }
        } catch (err) {
          _iterator9.e(err);
        } finally {
          _iterator9.f();
        }

        this.dispatchEvent(new Event('dispose'));
      }
    }, {
      key: "isCircular",
      value: function isCircular(node) {
        if (node === this) return true;
        var links = this.getLinks();

        var _iterator10 = _createForOfIteratorHelper(links),
            _step10;

        try {
          for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
            var link = _step10.value;

            if (link.outputElement.node.isCircular(node)) {
              return true;
            }
          }
        } catch (err) {
          _iterator10.e(err);
        } finally {
          _iterator10.f();
        }

        return false;
      }
    }, {
      key: "getLinks",
      value: function getLinks() {
        var links = [];

        var _iterator11 = _createForOfIteratorHelper(this.elements),
            _step11;

        try {
          for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
            var element = _step11.value;
            links.push.apply(links, _toConsumableArray(element.links));
          }
        } catch (err) {
          _iterator11.e(err);
        } finally {
          _iterator11.f();
        }

        return links;
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        var _this$getPosition = this.getPosition(),
            x = _this$getPosition.x,
            y = _this$getPosition.y,
            style = _this$getPosition.style;

        var elements = [];

        var _iterator12 = _createForOfIteratorHelper(this.elements),
            _step12;

        try {
          for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
            var element = _step12.value;
            elements.push(element.toJSON(data).id);
          }
        } catch (err) {
          _iterator12.e(err);
        } finally {
          _iterator12.f();
        }

        data.x = x;
        data.y = y;
        data.width = this.getWidth();
        data.elements = elements;

        if (style !== '') {
          data.style = style;
        }
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        this.setPosition(data.x, data.y);
        this.setWidth(data.width);

        if (data.style !== undefined) {
          this.setStyle(data.style);
        }

        var elements = this.elements;

        if (elements.length > 0) {
          var index = 0;

          var _iterator13 = _createForOfIteratorHelper(data.elements),
              _step13;

          try {
            for (_iterator13.s(); !(_step13 = _iterator13.n()).done;) {
              var id = _step13.value;
              data.objects[id] = elements[index++];
            }
          } catch (err) {
            _iterator13.e(err);
          } finally {
            _iterator13.f();
          }
        } else {
          var _iterator14 = _createForOfIteratorHelper(data.elements),
              _step14;

          try {
            for (_iterator14.s(); !(_step14 = _iterator14.n()).done;) {
              var _id4 = _step14.value;
              this.add(data.objects[_id4]);
            }
          } catch (err) {
            _iterator14.e(err);
          } finally {
            _iterator14.f();
          }
        }
      }
    }]);

    return Node;
  }(Serializer);

  _exports.Node = Node;
  Node.prototype.isNode = true;

  var drawLine = function drawLine(p1x, p1y, p2x, p2y, invert, size, color, ctx) {
    var offset = 100 * (invert ? -1 : 1);
    ctx.beginPath();
    ctx.moveTo(p1x, p1y);
    ctx.bezierCurveTo(p1x + offset, p1y, p2x - offset, p2y, p2x, p2y);
    ctx.lineWidth = size;
    ctx.strokeStyle = color;
    ctx.stroke();
  };

  var colors = ['#ff4444', '#44ff44', '#4444ff'];

  var Canvas = /*#__PURE__*/function (_Serializer4) {
    _inherits(Canvas, _Serializer4);

    var _super5 = _createSuper(Canvas);

    function Canvas() {
      var _this7;

      _classCallCheck(this, Canvas);

      _this7 = _super5.call(this);
      var dom = document.createElement('f-canvas');
      var contentDOM = document.createElement('f-content');
      var areaDOM = document.createElement('f-area');
      var canvas = document.createElement('canvas');
      var frontCanvas = document.createElement('canvas');
      var context = canvas.getContext('2d');
      var frontContext = frontCanvas.getContext('2d');
      _this7.dom = dom;
      _this7.contentDOM = contentDOM;
      _this7.areaDOM = areaDOM;
      _this7.canvas = canvas;
      _this7.frontCanvas = frontCanvas;
      _this7.context = context;
      _this7.frontContext = frontContext;
      _this7.width = 10000;
      _this7.height = 10000;
      _this7.clientX = 0;
      _this7.clientY = 0;
      _this7.relativeClientX = 0;
      _this7.relativeClientY = 0;
      _this7.zoom = 1;
      _this7.nodes = [];
      _this7.selected = null;
      _this7.updating = false;
      frontCanvas.className = 'front';
      contentDOM.style.left = toPX(_this7.centerX);
      contentDOM.style.top = toPX(_this7.centerY);
      areaDOM.style.width = "calc( 100% + ".concat(_this7.width, "px )");
      areaDOM.style.height = "calc( 100% + ".concat(_this7.height, "px )");
      dom.appendChild(canvas);
      dom.appendChild(frontCanvas);
      dom.appendChild(contentDOM);
      dom.appendChild(areaDOM);
      /*
      let zoomTouchData = null;
      	const onZoomStart = () => {
      		zoomTouchData = null;
      	};
      */

      var onZoom = function onZoom(e) {
        if (e.touches) {
          if (e.touches.length === 2) {
            e.preventDefault();
            e.stopImmediatePropagation();
            /*
            const clientX = ( e.touches[ 0 ].clientX + e.touches[ 1 ].clientX ) / 2;
            const clientY = ( e.touches[ 0 ].clientY + e.touches[ 1 ].clientY ) / 2;
            	const distance = Math.hypot(
            	e.touches[ 0 ].clientX - e.touches[ 1 ].clientX,
            	e.touches[ 0 ].clientY - e.touches[ 1 ].clientY
            );
            	if ( zoomTouchData === null ) {
            		zoomTouchData = {
            		distance
            	};
            	}
            	const delta = ( zoomTouchData.distance - distance );
            zoomTouchData.distance = distance;
            	let zoom = Math.min( Math.max( this.zoom - delta * .01, .5 ), 1.2 );
            	if ( zoom < .52 ) zoom = .5;
            else if ( zoom > .98 ) zoom = 1;
            	contentDOM.style.left = toPX( this.centerX / zoom );
            contentDOM.style.top = toPX( this.centerY / zoom );
            contentDOM.style.zoom = this.zoom = zoom;
            */
          }
        } else {
          e.preventDefault();
          e.stopImmediatePropagation();
          /*
          const delta = e.deltaY / 100;
          const zoom = Math.min( Math.max( this.zoom - delta * .1, .5 ), 1 );
          	contentDOM.style.left = toPX( this.centerX / zoom );
          contentDOM.style.top = toPX( this.centerY / zoom );
          contentDOM.style.zoom = this.zoom = zoom;
          */
        }
      };

      dom.addEventListener('wheel', onZoom);
      dom.addEventListener('touchmove', onZoom); //dom.addEventListener( 'touchstart', onZoomStart );

      draggableDOM(dom, function (data) {
        var delta = data.delta,
            isTouch = data.isTouch;

        if (!isTouch) {
          if (data.scrollTop === undefined) {
            data.scrollLeft = dom.scrollLeft;
            data.scrollTop = dom.scrollTop;
          }

          dom.scrollLeft = data.scrollLeft - delta.x;
          dom.scrollTop = data.scrollTop - delta.y;
        }

        if (data.dragging) {
          dom.classList.add('grabbing');
        } else {
          dom.classList.remove('grabbing');
        }
      }, 'dragging-canvas');

      _this7._onMoveEvent = function (e) {
        var event = e.touches ? e.touches[0] : e;

        var _assertThisInitialize = _assertThisInitialized(_this7),
            zoom = _assertThisInitialize.zoom,
            rect = _assertThisInitialize.rect;

        _this7.clientX = event.clientX;
        _this7.clientY = event.clientY;
        _this7.relativeClientX = (dom.scrollLeft - _this7.centerX + event.clientX - rect.left) / zoom;
        _this7.relativeClientY = (dom.scrollTop - _this7.centerY + event.clientY - rect.top) / zoom;
      };

      _this7._onContentLoaded = function () {
        _this7.centralize();
      };

      _this7._onUpdate = function () {
        _this7.update();
      };

      _this7.start();

      return _this7;
    }

    _createClass(Canvas, [{
      key: "rect",
      get: function get() {
        return this.dom.getBoundingClientRect();
      }
    }, {
      key: "relativeX",
      get: function get() {
        return this.dom.scrollLeft - this.centerX;
      }
    }, {
      key: "relativeY",
      get: function get() {
        return this.dom.scrollTop - this.centerY;
      }
    }, {
      key: "centerX",
      get: function get() {
        return this.width / 2;
      }
    }, {
      key: "centerY",
      get: function get() {
        return this.height / 2;
      }
    }, {
      key: "start",
      value: function start() {
        this.updating = true;
        document.addEventListener('wheel', this._onMoveEvent, true);
        document.addEventListener('mousedown', this._onMoveEvent, true);
        document.addEventListener('touchstart', this._onMoveEvent, true);
        document.addEventListener('mousemove', this._onMoveEvent, true);
        document.addEventListener('touchmove', this._onMoveEvent, true);
        document.addEventListener('DOMContentLoaded', this._onContentLoaded);
        requestAnimationFrame(this._onUpdate);
      }
    }, {
      key: "stop",
      value: function stop() {
        this.updating = false;
        document.removeEventListener('wheel', this._onMoveEvent, true);
        document.removeEventListener('mousedown', this._onMoveEvent, true);
        document.removeEventListener('touchstart', this._onMoveEvent, true);
        document.removeEventListener('mousemove', this._onMoveEvent, true);
        document.removeEventListener('touchmove', this._onMoveEvent, true);
        document.removeEventListener('DOMContentLoaded', this._onContentLoaded);
      }
    }, {
      key: "add",
      value: function add(node) {
        this.nodes.push(node);
        node.canvas = this;
        this.contentDOM.appendChild(node.dom);
        return this;
      }
    }, {
      key: "remove",
      value: function remove(node) {
        if (node === this.selected) {
          this.select();
        }

        this.unlink(node);
        var nodes = this.nodes;
        nodes.splice(nodes.indexOf(node), 1);
        node.canvas = null;
        this.contentDOM.removeChild(node.dom);
        return this;
      }
    }, {
      key: "clear",
      value: function clear() {
        var nodes = this.nodes;

        while (nodes.length > 0) {
          this.remove(nodes[0]);
        }

        return this;
      }
    }, {
      key: "unlink",
      value: function unlink(node) {
        var links = this.getLinks();

        var _iterator15 = _createForOfIteratorHelper(links),
            _step15;

        try {
          for (_iterator15.s(); !(_step15 = _iterator15.n()).done;) {
            var link = _step15.value;

            if (link.outputElement && link.outputElement.node === node) {
              link.inputElement.connect();
            }
          }
        } catch (err) {
          _iterator15.e(err);
        } finally {
          _iterator15.f();
        }
      }
    }, {
      key: "getLinks",
      value: function getLinks() {
        var links = [];

        var _iterator16 = _createForOfIteratorHelper(this.nodes),
            _step16;

        try {
          for (_iterator16.s(); !(_step16 = _iterator16.n()).done;) {
            var node = _step16.value;
            links.push.apply(links, _toConsumableArray(node.getLinks()));
          }
        } catch (err) {
          _iterator16.e(err);
        } finally {
          _iterator16.f();
        }

        return links;
      }
    }, {
      key: "centralize",
      value: function centralize() {
        this.dom.scroll(this.centerX, this.centerY);
        return this;
      }
    }, {
      key: "select",
      value: function select() {
        var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
        if (node === this.selected) return;
        var previousNode = this.selected;

        if (previousNode !== null) {
          previousNode.dom.classList.remove('selected');
          this.selected = null;
          dispatchEventList(previousNode.events.blur, previousNode);
        }

        if (node !== null) {
          node.dom.classList.add('selected');
          this.selected = node;
          dispatchEventList(node.events.focus, node);
        }
      }
    }, {
      key: "update",
      value: function update() {
        if (this.updating === false) return;
        requestAnimationFrame(this._onUpdate);
        var dom = this.dom,
            zoom = this.zoom,
            canvas = this.canvas,
            frontCanvas = this.frontCanvas,
            frontContext = this.frontContext,
            context = this.context;
        var width = window.innerWidth;
        var height = window.innerHeight;
        var domRect = this.rect;

        if (canvas.width !== width || canvas.height !== height) {
          canvas.width = width;
          canvas.height = height;
          frontCanvas.width = width;
          frontCanvas.height = height;
        }

        context.clearRect(0, 0, width, height);
        frontContext.clearRect(0, 0, width, height);
        context.globalCompositeOperation = 'lighter';
        frontContext.globalCompositeOperation = 'source-over';
        var links = this.getLinks();
        var aPos = {
          x: 0,
          y: 0
        };
        var bPos = {
          x: 0,
          y: 0
        };
        var offsetIORadius = 10;
        var dragging = '';

        var _iterator17 = _createForOfIteratorHelper(links),
            _step17;

        try {
          for (_iterator17.s(); !(_step17 = _iterator17.n()).done;) {
            var link = _step17.value;
            var lioElement = link.lioElement,
                rioElement = link.rioElement;
            var draggingLink = '';
            var length = 0;

            if (lioElement !== null) {
              var rect = lioElement.dom.getBoundingClientRect();
              length = Math.max(length, lioElement.rioLength);
              aPos.x = rect.x + rect.width;
              aPos.y = rect.y + rect.height / 2;
            } else {
              aPos.x = this.clientX;
              aPos.y = this.clientY;
              draggingLink = 'lio';
            }

            if (rioElement !== null) {
              var _rect = rioElement.dom.getBoundingClientRect();

              length = Math.max(length, rioElement.lioLength);
              bPos.x = _rect.x;
              bPos.y = _rect.y + _rect.height / 2;
            } else {
              bPos.x = this.clientX;
              bPos.y = this.clientY;
              draggingLink = 'rio';
            }

            dragging = dragging || draggingLink;
            var drawContext = draggingLink ? frontContext : context;

            if (draggingLink || length === 1) {
              if (draggingLink === 'rio') {
                aPos.x += offsetIORadius;
                bPos.x /= zoom;
                bPos.y /= zoom;
              } else if (draggingLink === 'lio') {
                bPos.x -= offsetIORadius;
                aPos.x /= zoom;
                aPos.y /= zoom;
              }

              drawLine(aPos.x * zoom, aPos.y * zoom, bPos.x * zoom, bPos.y * zoom, false, 2, '#ffffff', drawContext);
            } else {
              length = Math.min(length, 4);

              for (var i = 0; i < length; i++) {
                var color = colors[i] || '#ffffff';
                var marginY = 4;
                var rioLength = Math.min(lioElement.rioLength, length);
                var lioLength = Math.min(rioElement.lioLength, length);
                var aCenterY = rioLength * marginY * .5 - marginY / 2;
                var bCenterY = lioLength * marginY * .5 - marginY / 2;
                var aIndex = Math.min(i, rioLength - 1);
                var bIndex = Math.min(i, lioLength - 1);
                var aPosY = aIndex * marginY;
                var bPosY = bIndex * marginY;
                drawLine(aPos.x * zoom, (aPos.y + aPosY - aCenterY) * zoom, bPos.x * zoom, (bPos.y + bPosY - bCenterY) * zoom, false, 2, color, drawContext);
              }
            }
          }
        } catch (err) {
          _iterator17.e(err);
        } finally {
          _iterator17.f();
        }

        context.globalCompositeOperation = 'destination-in';
        context.fillRect(domRect.x, domRect.y, domRect.width, domRect.height);

        if (dragging !== '') {
          dom.classList.add('dragging-' + dragging);
        } else {
          dom.classList.remove('dragging-lio');
          dom.classList.remove('dragging-rio');
        }
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        var nodes = [];

        var _iterator18 = _createForOfIteratorHelper(this.nodes),
            _step18;

        try {
          for (_iterator18.s(); !(_step18 = _iterator18.n()).done;) {
            var node = _step18.value;
            nodes.push(node.toJSON(data).id);
          }
        } catch (err) {
          _iterator18.e(err);
        } finally {
          _iterator18.f();
        }

        data.nodes = nodes;
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        var _iterator19 = _createForOfIteratorHelper(data.nodes),
            _step19;

        try {
          for (_iterator19.s(); !(_step19 = _iterator19.n()).done;) {
            var id = _step19.value;
            this.add(data.objects[id]);
          }
        } catch (err) {
          _iterator19.e(err);
        } finally {
          _iterator19.f();
        }
      }
    }]);

    return Canvas;
  }(Serializer);

  _exports.Canvas = Canvas;

  var ButtonInput = /*#__PURE__*/function (_Input) {
    _inherits(ButtonInput, _Input);

    var _super6 = _createSuper(ButtonInput);

    function ButtonInput() {
      var _this8;

      var innterText = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

      _classCallCheck(this, ButtonInput);

      var dom = document.createElement('button');
      var spanDOM = document.createElement('span');
      dom.appendChild(spanDOM);
      var iconDOM = document.createElement('i');
      dom.appendChild(iconDOM);
      _this8 = _super6.call(this, dom);
      _this8.spanDOM = spanDOM;
      _this8.iconDOM = iconDOM;
      spanDOM.innerText = innterText;

      dom.onmouseover = function () {
        _this8.dispatchEvent(new Event('mouseover'));
      };

      dom.onclick = dom.ontouchstart = function (e) {
        e.preventDefault();
        e.stopPropagation();

        _this8.dispatchEvent(new Event('click'));
      };

      return _this8;
    }

    _createClass(ButtonInput, [{
      key: "setIcon",
      value: function setIcon(className) {
        this.iconDOM.className = className;
        return this;
      }
    }, {
      key: "setValue",
      value: function setValue(val) {
        this.spanDOM.innerText = val;
        return this;
      }
    }, {
      key: "getValue",
      value: function getValue() {
        return this.spanDOM.innerText;
      }
    }]);

    return ButtonInput;
  }(Input);

  _exports.ButtonInput = ButtonInput;

  var DraggableElement = /*#__PURE__*/function (_Element) {
    _inherits(DraggableElement, _Element);

    var _super7 = _createSuper(DraggableElement);

    function DraggableElement() {
      var _this9;

      var draggable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;

      _classCallCheck(this, DraggableElement);

      _this9 = _super7.call(this, true);
      _this9.draggable = draggable;

      var onDrag = function onDrag(e) {
        e.preventDefault();

        if (_this9.draggable === true) {
          draggableDOM(_this9.node.dom);
        }
      };

      var _assertThisInitialize2 = _assertThisInitialized(_this9),
          dom = _assertThisInitialize2.dom;

      dom.addEventListener('mousedown', onDrag, true);
      dom.addEventListener('touchstart', onDrag, true);
      return _this9;
    }

    return _createClass(DraggableElement);
  }(Element);

  _exports.DraggableElement = DraggableElement;

  var TitleElement = /*#__PURE__*/function (_DraggableElement) {
    _inherits(TitleElement, _DraggableElement);

    var _super8 = _createSuper(TitleElement);

    function TitleElement(title) {
      var _this10;

      var draggable = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;

      _classCallCheck(this, TitleElement);

      _this10 = _super8.call(this, draggable);

      var _assertThisInitialize3 = _assertThisInitialized(_this10),
          dom = _assertThisInitialize3.dom;

      dom.className = 'title';
      var spanDOM = document.createElement('span');
      spanDOM.innerText = title;
      var iconDOM = document.createElement('i');
      var toolbarDOM = document.createElement('f-toolbar');
      _this10.buttons = [];
      _this10.spanDOM = spanDOM;
      _this10.iconDOM = iconDOM;
      _this10.toolbarDOM = toolbarDOM;
      dom.appendChild(spanDOM);
      dom.appendChild(iconDOM);
      dom.appendChild(toolbarDOM);
      return _this10;
    }

    _createClass(TitleElement, [{
      key: "setIcon",
      value: function setIcon(value) {
        this.iconDOM.className = value;
        return this;
      }
    }, {
      key: "getIcon",
      value: function getIcon() {
        return this.iconDOM.className;
      }
    }, {
      key: "setTitle",
      value: function setTitle(value) {
        this.spanDOM.innerText = value;
        return this;
      }
    }, {
      key: "getTitle",
      value: function getTitle() {
        return this.spanDOM.innerText;
      }
    }, {
      key: "addButton",
      value: function addButton(button) {
        this.buttons.push(button);
        this.toolbarDOM.appendChild(button.dom);
        return this;
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        _get(_getPrototypeOf(TitleElement.prototype), "serialize", this).call(this, data);

        var title = this.getTitle();
        var icon = this.getIcon();
        data.title = title;

        if (icon !== '') {
          data.icon = icon;
        }
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        _get(_getPrototypeOf(TitleElement.prototype), "deserialize", this).call(this, data);

        this.setTitle(data.title);

        if (data.icon !== undefined) {
          this.setIcon(data.icon);
        }
      }
    }]);

    return TitleElement;
  }(DraggableElement);

  _exports.TitleElement = TitleElement;

  var ObjectNode = /*#__PURE__*/function (_Node) {
    _inherits(ObjectNode, _Node);

    var _super9 = _createSuper(ObjectNode);

    function ObjectNode(name, inputLength) {
      var _this11;

      var extra = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var width = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 300;

      _classCallCheck(this, ObjectNode);

      _this11 = _super9.call(this);

      _this11.setWidth(width);

      var title = new TitleElement(name).setExtra(extra).setOutput(inputLength);
      var closeButton = new ButtonInput('✖').onClick(function () {
        _this11.dispose();
      });
      title.addButton(closeButton);

      _this11.add(title);

      _this11.title = title;
      _this11.closeButton = closeButton;
      return _this11;
    }

    _createClass(ObjectNode, [{
      key: "setExtra",
      value: function setExtra(value) {
        this.title.setExtra(value);
        return this;
      }
    }, {
      key: "getExtra",
      value: function getExtra(value) {
        return this.title.getExtra();
      }
    }, {
      key: "invalidate",
      value: function invalidate() {
        this.title.dispatchEvent(new Event('connect'));
      }
    }]);

    return ObjectNode;
  }(Node);

  _exports.ObjectNode = ObjectNode;
  var ENTER_KEY$1 = 13;

  var StringInput = /*#__PURE__*/function (_Input2) {
    _inherits(StringInput, _Input2);

    var _super10 = _createSuper(StringInput);

    function StringInput() {
      var _this12;

      var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

      _classCallCheck(this, StringInput);

      var dom = document.createElement('input');
      _this12 = _super10.call(this, dom);
      dom.type = 'text';
      dom.value = value;
      dom.spellcheck = false;
      dom.autocomplete = 'off';

      dom.onblur = function () {
        _this12.dispatchEvent(new Event('blur'));
      };

      dom.onchange = function () {
        _this12.dispatchEvent(new Event('change'));
      };

      dom.onkeyup = function (e) {
        if (e.keyCode === ENTER_KEY$1) {
          e.target.blur();
        }

        e.stopPropagation();

        _this12.dispatchEvent(new Event('change'));
      };

      return _this12;
    }

    return _createClass(StringInput);
  }(Input);

  _exports.StringInput = StringInput;
  var ENTER_KEY = 13;

  var NumberInput = /*#__PURE__*/function (_Input3) {
    _inherits(NumberInput, _Input3);

    var _super11 = _createSuper(NumberInput);

    function NumberInput() {
      var _this13;

      var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
      var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -Infinity;
      var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Infinity;
      var step = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : .01;

      _classCallCheck(this, NumberInput);

      var dom = document.createElement('input');
      _this13 = _super11.call(this, dom);
      _this13.min = min;
      _this13.max = max;
      _this13.step = step;
      _this13.integer = false;
      dom.type = 'text';
      dom.className = 'number';
      dom.value = _this13._getString(value);
      dom.spellcheck = false;
      dom.autocomplete = 'off';

      dom.ondragstart = dom.oncontextmenu = function (e) {
        e.preventDefault();
        e.stopPropagation();
      };

      dom.onfocus = dom.onclick = function () {
        dom.select();
      };

      dom.onblur = function () {
        _this13.dispatchEvent(new Event('blur'));
      };

      dom.onchange = function () {
        _this13.dispatchEvent(new Event('change'));
      };

      dom.onkeydown = function (e) {
        if (e.key.length === 1 && /\d|\./.test(e.key) !== true) {
          return false;
        }

        if (e.keyCode === ENTER_KEY) {
          e.target.blur();
        }

        e.stopPropagation();
      };

      draggableDOM(dom, function (data) {
        var delta = data.delta;

        if (data.value === undefined) {
          data.value = _this13.getValue();
        }

        var diff = delta.x - delta.y;
        var value = data.value + diff * _this13.step;
        _this13.dom.value = _this13._getString(value.toFixed(_this13.precision));

        _this13.dispatchEvent(new Event('change'));
      });
      return _this13;
    }

    _createClass(NumberInput, [{
      key: "setRange",
      value: function setRange(min, max, step) {
        this.min = min;
        this.max = max;
        this.step = step;
        this.dispatchEvent(new Event('range'));
        return this.setValue(this.getValue());
      }
    }, {
      key: "precision",
      get: function get() {
        if (this.integer === true) return 0;
        var fract = this.step % 1;
        return fract !== 0 ? fract.toString().split('.')[1].length : 1;
      }
    }, {
      key: "setValue",
      value: function setValue(val) {
        var dispatch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
        return _get(_getPrototypeOf(NumberInput.prototype), "setValue", this).call(this, this._getString(val), dispatch);
      }
    }, {
      key: "getValue",
      value: function getValue() {
        return Number(this.dom.value);
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        var min = this.min,
            max = this.max;

        if (min !== -Infinity && max !== Infinity) {
          data.min = this.min;
          data.max = this.max;
          data.step = this.step;
        }

        _get(_getPrototypeOf(NumberInput.prototype), "serialize", this).call(this, data);
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        if (data.min !== undefined) {
          var min = this.min,
              max = this.max,
              step = this.step;
          this.setRange(min, max, step);
        }

        _get(_getPrototypeOf(NumberInput.prototype), "deserialize", this).call(this, data);
      }
    }, {
      key: "_getString",
      value: function _getString(value) {
        var num = Math.min(Math.max(Number(value), this.min), this.max);

        if (this.integer === true) {
          return Math.floor(num);
        } else {
          return num + (num % 1 ? '' : '.0');
        }
      }
    }]);

    return NumberInput;
  }(Input);

  _exports.NumberInput = NumberInput;

  var getStep = function getStep(min, max) {
    var sensibility = .001;
    return (max - min) * sensibility;
  };

  var SliderInput = /*#__PURE__*/function (_Input4) {
    _inherits(SliderInput, _Input4);

    var _super12 = _createSuper(SliderInput);

    function SliderInput() {
      var _this14;

      var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
      var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
      var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 100;

      _classCallCheck(this, SliderInput);

      var dom = document.createElement('f-subinputs');
      _this14 = _super12.call(this, dom);
      value = Math.min(Math.max(value, min), max);
      var step = getStep(min, max);
      var rangeDOM = document.createElement('input');
      rangeDOM.type = 'range';
      rangeDOM.min = min;
      rangeDOM.max = max;
      rangeDOM.step = step;
      rangeDOM.value = value;
      var field = new NumberInput(value, min, max, step);
      field.dom.className = 'range-value';
      field.onChange(function () {
        rangeDOM.value = field.getValue();
      });
      field.addEventListener('range', function () {
        rangeDOM.min = field.min;
        rangeDOM.max = field.max;
        rangeDOM.step = field.step;
        rangeDOM.value = field.getValue();
      });
      dom.appendChild(rangeDOM);
      dom.appendChild(field.dom);
      _this14.rangeDOM = rangeDOM;
      _this14.field = field;

      var updateRangeValue = function updateRangeValue() {
        var value = Number(rangeDOM.value);

        if (value !== _this14.max && value + _this14.step >= _this14.max) {
          // fix not end range fraction
          rangeDOM.value = value = _this14.max;
        }

        _this14.field.setValue(value);
      };

      draggableDOM(rangeDOM, function () {
        updateRangeValue();

        _this14.dispatchEvent(new Event('change'));
      }, '');
      return _this14;
    }

    _createClass(SliderInput, [{
      key: "min",
      get: function get() {
        return this.field.min;
      }
    }, {
      key: "max",
      get: function get() {
        return this.field.max;
      }
    }, {
      key: "step",
      get: function get() {
        return this.field.step;
      }
    }, {
      key: "setRange",
      value: function setRange(min, max) {
        this.field.setRange(min, max, getStep(min, max));
        this.dispatchEvent(new Event('range'));
        this.dispatchEvent(new Event('change'));
        return this;
      }
    }, {
      key: "setValue",
      value: function setValue(val) {
        var dispatch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
        this.field.setValue(val);
        this.rangeDOM.value = val;
        if (dispatch) this.dispatchEvent(new Event('change'));
        return this;
      }
    }, {
      key: "getValue",
      value: function getValue() {
        return this.field.getValue();
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        data.min = this.min;
        data.max = this.max;

        _get(_getPrototypeOf(SliderInput.prototype), "serialize", this).call(this, data);
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        var min = data.min,
            max = data.max;
        this.setRange(min, max);

        _get(_getPrototypeOf(SliderInput.prototype), "deserialize", this).call(this, data);
      }
    }]);

    return SliderInput;
  }(Input);

  _exports.SliderInput = SliderInput;

  var ColorInput = /*#__PURE__*/function (_Input5) {
    _inherits(ColorInput, _Input5);

    var _super13 = _createSuper(ColorInput);

    function ColorInput() {
      var _this15;

      var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0x0099ff;

      _classCallCheck(this, ColorInput);

      var dom = document.createElement('input');
      _this15 = _super13.call(this, dom);
      dom.type = 'color';
      dom.value = toHex(value);

      dom.oninput = function () {
        _this15.dispatchEvent(new Event('change'));
      };

      return _this15;
    }

    _createClass(ColorInput, [{
      key: "setValue",
      value: function setValue(value) {
        var dispatch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
        return _get(_getPrototypeOf(ColorInput.prototype), "setValue", this).call(this, toHex(value), dispatch);
      }
    }, {
      key: "getValue",
      value: function getValue() {
        return parseInt(_get(_getPrototypeOf(ColorInput.prototype), "getValue", this).call(this).substr(1), 16);
      }
    }]);

    return ColorInput;
  }(Input);

  _exports.ColorInput = ColorInput;

  var TextInput = /*#__PURE__*/function (_Input6) {
    _inherits(TextInput, _Input6);

    var _super14 = _createSuper(TextInput);

    function TextInput() {
      var _this16;

      var innerText = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

      _classCallCheck(this, TextInput);

      var dom = document.createElement('textarea');
      _this16 = _super14.call(this, dom);
      dom.innerText = innerText;
      return _this16;
    }

    _createClass(TextInput, [{
      key: "setValue",
      value: function setValue(val) {
        this.dom.innerText = val;
        return this;
      }
    }, {
      key: "getValue",
      value: function getValue() {
        return this.dom.innerText;
      }
    }]);

    return TextInput;
  }(Input);

  _exports.TextInput = TextInput;

  var LabelElement = /*#__PURE__*/function (_Element2) {
    _inherits(LabelElement, _Element2);

    var _super15 = _createSuper(LabelElement);

    function LabelElement() {
      var _this17;

      var label = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
      var align = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';

      _classCallCheck(this, LabelElement);

      _this17 = _super15.call(this);
      _this17.labelDOM = document.createElement('f-label');
      _this17.inputsDOM = document.createElement('f-inputs');
      var spanDOM = document.createElement('span');
      var iconDOM = document.createElement('i');
      _this17.spanDOM = spanDOM;
      _this17.iconDOM = iconDOM;

      _this17.labelDOM.appendChild(_this17.spanDOM);

      _this17.labelDOM.appendChild(_this17.iconDOM);

      _this17.dom.appendChild(_this17.labelDOM);

      _this17.dom.appendChild(_this17.inputsDOM);

      _this17.setLabel(label);

      _this17.setAlign(align);

      return _this17;
    }

    _createClass(LabelElement, [{
      key: "setIcon",
      value: function setIcon(value) {
        this.iconDOM.className = value;
        return this;
      }
    }, {
      key: "getIcon",
      value: function getIcon() {
        return this.iconDOM.className;
      }
    }, {
      key: "setAlign",
      value: function setAlign(align) {
        this.labelDOM.className = align;
      }
    }, {
      key: "setLabel",
      value: function setLabel(val) {
        this.spanDOM.innerText = val;
      }
    }, {
      key: "getLabel",
      value: function getLabel() {
        return this.spanDOM.innerText;
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        _get(_getPrototypeOf(LabelElement.prototype), "serialize", this).call(this, data);

        var label = this.getLabel();
        var icon = this.getIcon();
        data.label = label;

        if (icon !== '') {
          data.icon = icon;
        }
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        _get(_getPrototypeOf(LabelElement.prototype), "deserialize", this).call(this, data);

        this.setLabel(data.label);

        if (data.icon !== undefined) {
          this.setIcon(data.icon);
        }
      }
    }]);

    return LabelElement;
  }(Element);

  _exports.LabelElement = LabelElement;

  var PanelNode = /*#__PURE__*/function (_Node2) {
    _inherits(PanelNode, _Node2);

    var _super16 = _createSuper(PanelNode);

    function PanelNode() {
      var _this18;

      var title = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Panel';
      var align = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top-right';

      _classCallCheck(this, PanelNode);

      _this18 = _super16.call(this);
      var titleElement = new TitleElement(title);

      _this18.add(titleElement);

      var collapseButton = new ButtonInput('🗕');
      collapseButton.onClick(function () {
        _this18.setCollapse(!_this18.collapsed);
      });
      titleElement.addButton(collapseButton);
      _this18.collapseButton = collapseButton;
      _this18.titleElement = titleElement;
      _this18.align = align;
      _this18.collapsed = false;

      _this18.setAlign(align);

      _this18.setStyle('rouded');

      return _this18;
    }

    _createClass(PanelNode, [{
      key: "setCollapse",
      value: function setCollapse(value) {
        var cssClass = 'closed';
        this.dom.classList.remove(cssClass);
        this.collapsed = value;
        this.collapseButton.value = value ? '🗖' : '🗕';

        if (value === true) {
          this.dom.classList.add(cssClass);
        }

        return this;
      }
    }, {
      key: "setAlign",
      value: function setAlign(align) {
        if (this.align) this.dom.classList.remove(this.align);
        this.dom.classList.add(align);
        this.align = align;
        return this;
      }
    }, {
      key: "addInput",
      value: function addInput(inputClass, object, property) {
        var value = object[property];

        for (var _len2 = arguments.length, params = new Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {
          params[_key2 - 3] = arguments[_key2];
        }

        var input = _construct(inputClass, [value].concat(params));

        input.onChange(function () {
          object[property] = input.value;
        });
        this.add(new LabelElement(property).add(input));
        return input;
      }
    }, {
      key: "addSlider",
      value: function addSlider(object, property, min, max) {
        return this.addInput(SliderInput, object, property, min, max);
      }
    }, {
      key: "addNumber",
      value: function addNumber(object, property) {
        return this.addInput(NumberInput, object, property);
      }
    }, {
      key: "addColor",
      value: function addColor(object, property) {
        return this.addInput(ColorInput, object, property);
      }
    }, {
      key: "addString",
      value: function addString(object, property) {
        return this.addInput(StringInput, object, property);
      }
    }, {
      key: "addText",
      value: function addText(object, property) {
        var input = this.addInput(TextInput, object, property);
        input.element.setHeight(70);
        return input;
      }
    }, {
      key: "addButton",
      value: function addButton(name) {
        var input = new ButtonInput(name);
        this.add(new Element().setHeight(34).add(input));
        return input;
      }
    }]);

    return PanelNode;
  }(Node);

  _exports.PanelNode = PanelNode;

  var Menu = /*#__PURE__*/function (_EventTarget2) {
    _inherits(Menu, _EventTarget2);

    var _super17 = _createSuper(Menu);

    function Menu(className) {
      var _this19;

      var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

      _classCallCheck(this, Menu);

      _this19 = _super17.call(this);
      var dom = document.createElement('f-menu');
      dom.className = className + ' hidden';
      _this19.dom = dom;
      _this19.visible = false;
      _this19.subMenus = new WeakMap();
      _this19.domButtons = new WeakMap();
      _this19.events = {
        'context': []
      };

      _this19.addEventListener('context', function () {
        dispatchEventList(_this19.events.context, _assertThisInitialized(_this19));
      });

      _this19._lastButtonClick = null;

      _this19._onButtonClick = function () {
        var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
        var button = e ? e.target : null;

        if (_this19._lastButtonClick) {
          _this19._lastButtonClick.dom.parentElement.classList.remove('active');
        }

        _this19._lastButtonClick = button;

        if (button) {
          if (_this19.subMenus.has(button)) {
            _this19.subMenus.get(button)._onButtonClick();
          }

          button.dom.parentElement.classList.add('active');
        }
      };

      _this19._onButtonMouseOver = function (e) {
        var button = e.target;

        if (_this19.subMenus.has(button) && _this19._lastButtonClick !== button) {
          _this19._onButtonClick();
        }
      };

      _this19.setTarget(target);

      return _this19;
    }

    _createClass(Menu, [{
      key: "onContext",
      value: function onContext(callback) {
        this.events.context.push(callback);
        return this;
      }
    }, {
      key: "show",
      value: function show() {
        var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
        var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

        this._onButtonClick();

        if (x !== null && y !== null) {
          this.setPosition(x, y);
        }

        this.dom.classList.remove('hidden');
        this.visible = true;
        this.dispatchEvent(new Event('show'));
        return this;
      }
    }, {
      key: "hide",
      value: function hide() {
        this.dom.classList.add('hidden');
        this.dispatchEvent(new Event('hide'));
        this.visible = false;
      }
    }, {
      key: "setTarget",
      value: function setTarget() {
        var _this20 = this;

        var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

        if (target !== null) {
          var onContextMenu = function onContextMenu(e) {
            e.preventDefault();
            if (e.pointerType !== 'mouse' || e.pageX === 0 && e.pageY === 0) return;

            var rect = _this20.target.getBoundingClientRect();

            _this20.dispatchEvent(new Event('context'));

            _this20.show(e.pageX - rect.left, e.pageY - rect.top);
          };

          var onDown = function onDown(e) {
            if (_this20.visible === true && e.target.closest('f-menu') === null) {
              _this20.hide();
            }
          };

          this.target = target;
          target.addEventListener('mousedown', onDown, true);
          target.addEventListener('touchstart', onDown, true);
          target.addEventListener('contextmenu', onContextMenu, false);
          target.appendChild(this.dom);
        }

        return this;
      }
    }, {
      key: "add",
      value: function add(button) {
        var submenu = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
        var liDOM = document.createElement('f-item');

        if (submenu !== null) {
          liDOM.classList.add('submenu');
          liDOM.appendChild(submenu.dom);
          this.subMenus.set(button, submenu);
        }

        liDOM.appendChild(button.dom);
        button.addEventListener('click', this._onButtonClick);
        button.addEventListener('mouseover', this._onButtonMouseOver);
        this.dom.appendChild(liDOM);
        this.domButtons.set(liDOM, button);
        return this;
      }
    }, {
      key: "setPosition",
      value: function setPosition(x, y) {
        var dom = this.dom;
        dom.style.left = toPX(x);
        dom.style.top = toPX(y);
        return this;
      }
    }]);

    return Menu;
  }( /*#__PURE__*/_wrapNativeSuper(EventTarget));

  _exports.Menu = Menu;
  var lastContext = null;

  var ContextMenu = /*#__PURE__*/function (_Menu) {
    _inherits(ContextMenu, _Menu);

    var _super18 = _createSuper(ContextMenu);

    function ContextMenu() {
      var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      _classCallCheck(this, ContextMenu);

      return _super18.call(this, 'context', target);
    }

    _createClass(ContextMenu, [{
      key: "show",
      value: function show(x, y) {
        if (lastContext !== null) {
          lastContext.hide();
        }

        lastContext = this;
        return _get(_getPrototypeOf(ContextMenu.prototype), "show", this).call(this, x, y);
      }
    }, {
      key: "hide",
      value: function hide() {
        if (lastContext === this) {
          lastContext = null;
        }

        return _get(_getPrototypeOf(ContextMenu.prototype), "hide", this).call(this);
      }
    }]);

    return ContextMenu;
  }(Menu);

  _exports.ContextMenu = ContextMenu;

  var CircleMenu = /*#__PURE__*/function (_Menu2) {
    _inherits(CircleMenu, _Menu2);

    var _super19 = _createSuper(CircleMenu);

    function CircleMenu() {
      var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

      _classCallCheck(this, CircleMenu);

      return _super19.call(this, 'circle', target);
    }

    return _createClass(CircleMenu);
  }(Menu);

  _exports.CircleMenu = CircleMenu;

  var SelectInput = /*#__PURE__*/function (_Input7) {
    _inherits(SelectInput, _Input7);

    var _super20 = _createSuper(SelectInput);

    function SelectInput() {
      var _this21;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];

      _classCallCheck(this, SelectInput);

      var dom = document.createElement('select');
      _this21 = _super20.call(this, dom);

      dom.onchange = function () {
        _this21.dispatchEvent(new Event('change'));
      };

      _this21.setOptions(options);

      return _this21;
    }

    _createClass(SelectInput, [{
      key: "setOptions",
      value: function setOptions(options) {
        var dom = this.dom;
        this.options = options;
        dom.innerHTML = '';

        for (var index = 0; index < options.length; index++) {
          var opt = options[index];

          if (typeof opt === 'string') {
            opt = {
              name: opt,
              value: index
            };
          }

          var option = document.createElement('option');
          option.innerText = opt.name;
          option.value = opt.value;
          dom.appendChild(option);
        }

        return this;
      }
    }, {
      key: "getOptions",
      value: function getOptions() {
        return this._options;
      }
    }, {
      key: "serialize",
      value: function serialize(data) {
        data.options = _toConsumableArray(this.options);

        _get(_getPrototypeOf(SelectInput.prototype), "serialize", this).call(this, data);
      }
    }, {
      key: "deserialize",
      value: function deserialize(data) {
        var currentOptions = this.options;

        if (currentOptions.length > 0) {
          this.setOptions(data.options);
        }

        _get(_getPrototypeOf(SelectInput.prototype), "deserialize", this).call(this, data);
      }
    }]);

    return SelectInput;
  }(Input);

  _exports.SelectInput = SelectInput;

  var ToggleInput = /*#__PURE__*/function (_Input8) {
    _inherits(ToggleInput, _Input8);

    var _super21 = _createSuper(ToggleInput);

    function ToggleInput() {
      var _this22;

      var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;

      _classCallCheck(this, ToggleInput);

      var dom = document.createElement('input');
      _this22 = _super21.call(this, dom);
      dom.type = 'checkbox';
      dom.className = 'toggle';
      dom.checked = value;
      return _this22;
    }

    _createClass(ToggleInput, [{
      key: "setValue",
      value: function setValue(val) {
        this.dom.checked = val;
        this.dispatchEvent(new Event('change'));
        return this;
      }
    }, {
      key: "getValue",
      value: function getValue() {
        return this.dom.checked;
      }
    }]);

    return ToggleInput;
  }(Input);

  _exports.ToggleInput = ToggleInput;
  var Flow = /*#__PURE__*/Object.freeze({
    __proto__: null,
    Element: Element,
    Input: Input,
    Node: Node,
    Canvas: Canvas,
    Serializer: Serializer,
    ObjectNode: ObjectNode,
    PanelNode: PanelNode,
    Menu: Menu,
    ContextMenu: ContextMenu,
    CircleMenu: CircleMenu,
    DraggableElement: DraggableElement,
    LabelElement: LabelElement,
    TitleElement: TitleElement,
    ButtonInput: ButtonInput,
    ColorInput: ColorInput,
    NumberInput: NumberInput,
    SelectInput: SelectInput,
    SliderInput: SliderInput,
    StringInput: StringInput,
    TextInput: TextInput,
    ToggleInput: ToggleInput
  });

  var Loader = /*#__PURE__*/function (_EventTarget3) {
    _inherits(Loader, _EventTarget3);

    var _super22 = _createSuper(Loader);

    function Loader() {
      var _this23;

      var parseType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Loader.DEFAULT;

      _classCallCheck(this, Loader);

      _this23 = _super22.call(this);
      _this23.parseType = parseType;
      _this23.events = {
        'load': []
      };
      return _this23;
    }

    _createClass(Loader, [{
      key: "setParseType",
      value: function setParseType(type) {
        this.parseType = type;
        return this;
      }
    }, {
      key: "getParseType",
      value: function getParseType() {
        return this.parseType;
      }
    }, {
      key: "onLoad",
      value: function onLoad(callback) {
        this.events.load.push(callback);
        return this;
      }
    }, {
      key: "load",
      value: function () {
        var _load = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(url) {
          var _this24 = this;

          var lib,
              _args = arguments;
          return regeneratorRuntime.wrap(function _callee$(_context) {
            while (1) {
              switch (_context.prev = _context.next) {
                case 0:
                  lib = _args.length > 1 && _args[1] !== undefined ? _args[1] : null;
                  _context.next = 3;
                  return fetch(url).then(function (response) {
                    return response.json();
                  }).then(function (result) {
                    _this24.data = _this24.parse(result, lib);
                    dispatchEventList(_this24.events.load, _this24);
                    return _this24.data;
                  }).catch(function (err) {
                    console.error('Loader:', err);
                  });

                case 3:
                  return _context.abrupt("return", _context.sent);

                case 4:
                case "end":
                  return _context.stop();
              }
            }
          }, _callee);
        }));

        function load(_x) {
          return _load.apply(this, arguments);
        }

        return load;
      }()
    }, {
      key: "parse",
      value: function parse(json) {
        var lib = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
        json = this._parseObjects(json, lib);
        var parseType = this.parseType;

        if (parseType === Loader.DEFAULT) {
          var flowObj = new Flow[json.type]();

          if (flowObj.getSerializable()) {
            flowObj.deserialize(json);
          }

          return flowObj;
        } else if (parseType === Loader.OBJECTS) {
          return json;
        }
      }
    }, {
      key: "_parseObjects",
      value: function _parseObjects(json) {
        var lib = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
        json = _objectSpread({}, json);
        var objects = {};

        for (var id in json.objects) {
          var obj = json.objects[id];
          obj.objects = objects;
          var Class = lib && lib[obj.type] ? lib[obj.type] : Flow[obj.type];
          objects[id] = new Class();
        }

        var ref = new WeakMap();

        var deserializePass = function deserializePass() {
          var prop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;

          for (var _id5 in json.objects) {
            var newObject = objects[_id5];

            if (ref.has(newObject) === false && (prop === null || newObject[prop] === true)) {
              ref.set(newObject, true);

              if (newObject.getSerializable()) {
                newObject.deserialize(json.objects[_id5]);
              }
            }
          }
        };

        deserializePass('isNode');
        deserializePass('isElement');
        deserializePass('isInput');
        deserializePass();
        json.objects = objects;
        return json;
      }
    }]);

    return Loader;
  }( /*#__PURE__*/_wrapNativeSuper(EventTarget));

  _exports.Loader = Loader;
  Loader.DEFAULT = 'default';
  Loader.OBJECTS = 'objects';
});