interact

JavaScript drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE9+).

Tính đến 26-08-2025. Xem phiên bản mới nhất.

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greatest.deepsurf.us/scripts/547397/1649829/interact.js

/**
 * interact.js 1.10.27
 *
 * Copyright (c) 2012-present Taye Adeyemi <[email protected]>
 * Released under the MIT License.
 * https://raw.github.com/taye/interact.js/main/LICENSE
 */

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.interact = factory());
})(this, (function () { 'use strict';

  function ownKeys(e, r) {
    var t = Object.keys(e);
    if (Object.getOwnPropertySymbols) {
      var o = Object.getOwnPropertySymbols(e);
      r && (o = o.filter(function (r) {
        return Object.getOwnPropertyDescriptor(e, r).enumerable;
      })), t.push.apply(t, o);
    }
    return t;
  }
  function _objectSpread2(e) {
    for (var r = 1; r < arguments.length; r++) {
      var t = null != arguments[r] ? arguments[r] : {};
      r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
        _defineProperty(e, r, t[r]);
      }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
        Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
      });
    }
    return e;
  }
  function _typeof(o) {
    "@babel/helpers - typeof";

    return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
      return typeof o;
    } : function (o) {
      return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
    }, _typeof(o);
  }
  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, _toPropertyKey(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 _defineProperty(obj, key, value) {
    key = _toPropertyKey(key);
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }
    return obj;
  }
  function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function");
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        writable: true,
        configurable: true
      }
    });
    Object.defineProperty(subClass, "prototype", {
      writable: false
    });
    if (superClass) _setPrototypeOf(subClass, superClass);
  }
  function _getPrototypeOf(o) {
    _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
      return o.__proto__ || Object.getPrototypeOf(o);
    };
    return _getPrototypeOf(o);
  }
  function _setPrototypeOf(o, p) {
    _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
      o.__proto__ = p;
      return o;
    };
    return _setPrototypeOf(o, p);
  }
  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 _assertThisInitialized(self) {
    if (self === void 0) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return self;
  }
  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 _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 _superPropBase(object, property) {
    while (!Object.prototype.hasOwnProperty.call(object, property)) {
      object = _getPrototypeOf(object);
      if (object === null) break;
    }
    return object;
  }
  function _get() {
    if (typeof Reflect !== "undefined" && Reflect.get) {
      _get = Reflect.get.bind();
    } 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 _toPrimitive(input, hint) {
    if (typeof input !== "object" || input === null) return input;
    var prim = input[Symbol.toPrimitive];
    if (prim !== undefined) {
      var res = prim.call(input, hint || "default");
      if (typeof res !== "object") return res;
      throw new TypeError("@@toPrimitive must return a primitive value.");
    }
    return (hint === "string" ? String : Number)(input);
  }
  function _toPropertyKey(arg) {
    var key = _toPrimitive(arg, "string");
    return typeof key === "symbol" ? key : String(key);
  }

  var isWindow = (function (thing) {
    return !!(thing && thing.Window) && thing instanceof thing.Window;
  });

  var realWindow = undefined;
  var win = undefined;
  function init$3(window) {
    // get wrapped window if using Shadow DOM polyfill

    realWindow = window;

    // create a TextNode
    var el = window.document.createTextNode('');

    // check if it's wrapped by a polyfill
    if (el.ownerDocument !== window.document && typeof window.wrap === 'function' && window.wrap(el) === el) {
      // use wrapped window
      window = window.wrap(window);
    }
    win = window;
  }
  if (typeof window !== 'undefined' && !!window) {
    init$3(window);
  }
  function getWindow(node) {
    if (isWindow(node)) {
      return node;
    }
    var rootNode = node.ownerDocument || node;
    return rootNode.defaultView || win.window;
  }

  var window$1 = function window(thing) {
    return thing === win || isWindow(thing);
  };
  var docFrag = function docFrag(thing) {
    return object(thing) && thing.nodeType === 11;
  };
  var object = function object(thing) {
    return !!thing && _typeof(thing) === 'object';
  };
  var func = function func(thing) {
    return typeof thing === 'function';
  };
  var number = function number(thing) {
    return typeof thing === 'number';
  };
  var bool = function bool(thing) {
    return typeof thing === 'boolean';
  };
  var string = function string(thing) {
    return typeof thing === 'string';
  };
  var element = function element(thing) {
    if (!thing || _typeof(thing) !== 'object') {
      return false;
    }
    var _window = getWindow(thing) || win;
    return /object|function/.test(typeof Element === "undefined" ? "undefined" : _typeof(Element)) ? thing instanceof Element || thing instanceof _window.Element : thing.nodeType === 1 && typeof thing.nodeName === 'string';
  };
  var plainObject = function plainObject(thing) {
    return object(thing) && !!thing.constructor && /function Object\b/.test(thing.constructor.toString());
  };
  var array = function array(thing) {
    return object(thing) && typeof thing.length !== 'undefined' && func(thing.splice);
  };
  var is = {
    window: window$1,
    docFrag: docFrag,
    object: object,
    func: func,
    number: number,
    bool: bool,
    string: string,
    element: element,
    plainObject: plainObject,
    array: array
  };

  function install$g(scope) {
    var actions = scope.actions,
      Interactable = scope.Interactable,
      defaults = scope.defaults;
    Interactable.prototype.draggable = drag.draggable;
    actions.map.drag = drag;
    actions.methodDict.drag = 'draggable';
    defaults.actions.drag = drag.defaults;
  }
  function beforeMove(_ref) {
    var interaction = _ref.interaction;
    if (interaction.prepared.name !== 'drag') return;
    var axis = interaction.prepared.axis;
    if (axis === 'x') {
      interaction.coords.cur.page.y = interaction.coords.start.page.y;
      interaction.coords.cur.client.y = interaction.coords.start.client.y;
      interaction.coords.velocity.client.y = 0;
      interaction.coords.velocity.page.y = 0;
    } else if (axis === 'y') {
      interaction.coords.cur.page.x = interaction.coords.start.page.x;
      interaction.coords.cur.client.x = interaction.coords.start.client.x;
      interaction.coords.velocity.client.x = 0;
      interaction.coords.velocity.page.x = 0;
    }
  }
  function move$1(_ref2) {
    var iEvent = _ref2.iEvent,
      interaction = _ref2.interaction;
    if (interaction.prepared.name !== 'drag') return;
    var axis = interaction.prepared.axis;
    if (axis === 'x' || axis === 'y') {
      var opposite = axis === 'x' ? 'y' : 'x';
      iEvent.page[opposite] = interaction.coords.start.page[opposite];
      iEvent.client[opposite] = interaction.coords.start.client[opposite];
      iEvent.delta[opposite] = 0;
    }
  }
  var draggable = function draggable(options) {
    if (is.object(options)) {
      this.options.drag.enabled = options.enabled !== false;
      this.setPerAction('drag', options);
      this.setOnEvents('drag', options);
      if (/^(xy|x|y|start)$/.test(options.lockAxis)) {
        this.options.drag.lockAxis = options.lockAxis;
      }
      if (/^(xy|x|y)$/.test(options.startAxis)) {
        this.options.drag.startAxis = options.startAxis;
      }
      return this;
    }
    if (is.bool(options)) {
      this.options.drag.enabled = options;
      return this;
    }
    return this.options.drag;
  };
  var drag = {
    id: 'actions/drag',
    install: install$g,
    listeners: {
      'interactions:before-action-move': beforeMove,
      'interactions:action-resume': beforeMove,
      // dragmove
      'interactions:action-move': move$1,
      'auto-start:check': function autoStartCheck(arg) {
        var interaction = arg.interaction,
          interactable = arg.interactable,
          buttons = arg.buttons;
        var dragOptions = interactable.options.drag;
        if (!(dragOptions && dragOptions.enabled) ||
        // check mouseButton setting if the pointer is down
        interaction.pointerIsDown && /mouse|pointer/.test(interaction.pointerType) && (buttons & interactable.options.drag.mouseButtons) === 0) {
          return undefined;
        }
        arg.action = {
          name: 'drag',
          axis: dragOptions.lockAxis === 'start' ? dragOptions.startAxis : dragOptions.lockAxis
        };
        return false;
      }
    },
    draggable: draggable,
    beforeMove: beforeMove,
    move: move$1,
    defaults: {
      startAxis: 'xy',
      lockAxis: 'xy'
    },
    getCursor: function getCursor() {
      return 'move';
    },
    filterEventType: function filterEventType(type) {
      return type.search('drag') === 0;
    }
  };
  var drag$1 = drag;

  var domObjects = {
    init: init$2,
    document: null,
    DocumentFragment: null,
    SVGElement: null,
    SVGSVGElement: null,
    SVGElementInstance: null,
    Element: null,
    HTMLElement: null,
    Event: null,
    Touch: null,
    PointerEvent: null
  };
  function blank() {}
  var domObjects$1 = domObjects;
  function init$2(window) {
    var win = window;
    domObjects.document = win.document;
    domObjects.DocumentFragment = win.DocumentFragment || blank;
    domObjects.SVGElement = win.SVGElement || blank;
    domObjects.SVGSVGElement = win.SVGSVGElement || blank;
    domObjects.SVGElementInstance = win.SVGElementInstance || blank;
    domObjects.Element = win.Element || blank;
    domObjects.HTMLElement = win.HTMLElement || domObjects.Element;
    domObjects.Event = win.Event;
    domObjects.Touch = win.Touch || blank;
    domObjects.PointerEvent = win.PointerEvent || win.MSPointerEvent;
  }

  var browser = {
    init: init$1,
    supportsTouch: null,
    supportsPointerEvent: null,
    isIOS7: null,
    isIOS: null,
    isIe9: null,
    isOperaMobile: null,
    prefixedMatchesSelector: null,
    pEventTypes: null,
    wheelEvent: null
  };
  function init$1(window) {
    var Element = domObjects$1.Element;
    var navigator = window.navigator || {};

    // Does the browser support touch input?
    browser.supportsTouch = 'ontouchstart' in window || is.func(window.DocumentTouch) && domObjects$1.document instanceof window.DocumentTouch;

    // Does the browser support PointerEvents
    // https://github.com/taye/interact.js/issues/703#issuecomment-471570492
    browser.supportsPointerEvent = navigator.pointerEnabled !== false && !!domObjects$1.PointerEvent;
    browser.isIOS = /iP(hone|od|ad)/.test(navigator.platform);

    // scrolling doesn't change the result of getClientRects on iOS 7
    browser.isIOS7 = /iP(hone|od|ad)/.test(navigator.platform) && /OS 7[^\d]/.test(navigator.appVersion);
    browser.isIe9 = /MSIE 9/.test(navigator.userAgent);

    // Opera Mobile must be handled differently
    browser.isOperaMobile = navigator.appName === 'Opera' && browser.supportsTouch && /Presto/.test(navigator.userAgent);

    // prefix matchesSelector
    browser.prefixedMatchesSelector = 'matches' in Element.prototype ? 'matches' : 'webkitMatchesSelector' in Element.prototype ? 'webkitMatchesSelector' : 'mozMatchesSelector' in Element.prototype ? 'mozMatchesSelector' : 'oMatchesSelector' in Element.prototype ? 'oMatchesSelector' : 'msMatchesSelector';
    browser.pEventTypes = browser.supportsPointerEvent ? domObjects$1.PointerEvent === window.MSPointerEvent ? {
      up: 'MSPointerUp',
      down: 'MSPointerDown',
      over: 'mouseover',
      out: 'mouseout',
      move: 'MSPointerMove',
      cancel: 'MSPointerCancel'
    } : {
      up: 'pointerup',
      down: 'pointerdown',
      over: 'pointerover',
      out: 'pointerout',
      move: 'pointermove',
      cancel: 'pointercancel'
    } : null;

    // because Webkit and Opera still use 'mousewheel' event type
    browser.wheelEvent = domObjects$1.document && 'onmousewheel' in domObjects$1.document ? 'mousewheel' : 'wheel';
  }
  var browser$1 = browser;

  function nodeContains(parent, child) {
    if (parent.contains) {
      return parent.contains(child);
    }
    while (child) {
      if (child === parent) {
        return true;
      }
      child = child.parentNode;
    }
    return false;
  }
  function closest(element, selector) {
    while (is.element(element)) {
      if (matchesSelector(element, selector)) {
        return element;
      }
      element = parentNode(element);
    }
    return null;
  }
  function parentNode(node) {
    var parent = node.parentNode;
    if (is.docFrag(parent)) {
      // skip past #shado-root fragments
      // tslint:disable-next-line
      while ((parent = parent.host) && is.docFrag(parent)) {
        continue;
      }
      return parent;
    }
    return parent;
  }
  function matchesSelector(element, selector) {
    // remove /deep/ from selectors if shadowDOM polyfill is used
    if (win !== realWindow) {
      selector = selector.replace(/\/deep\//g, ' ');
    }
    return element[browser$1.prefixedMatchesSelector](selector);
  }
  var getParent = function getParent(el) {
    return el.parentNode || el.host;
  };

  // Test for the element that's "above" all other qualifiers
  function indexOfDeepestElement(elements) {
    var deepestNodeParents = [];
    var deepestNodeIndex;
    for (var i = 0; i < elements.length; i++) {
      var currentNode = elements[i];
      var deepestNode = elements[deepestNodeIndex];

      // node may appear in elements array multiple times
      if (!currentNode || i === deepestNodeIndex) {
        continue;
      }
      if (!deepestNode) {
        deepestNodeIndex = i;
        continue;
      }
      var currentNodeParent = getParent(currentNode);
      var deepestNodeParent = getParent(deepestNode);

      // check if the deepest or current are document.documentElement/rootElement
      // - if the current node is, do nothing and continue
      if (currentNodeParent === currentNode.ownerDocument) {
        continue;
      }
      // - if deepest is, update with the current node and continue to next
      else if (deepestNodeParent === currentNode.ownerDocument) {
        deepestNodeIndex = i;
        continue;
      }

      // compare zIndex of siblings
      if (currentNodeParent === deepestNodeParent) {
        if (zIndexIsHigherThan(currentNode, deepestNode)) {
          deepestNodeIndex = i;
        }
        continue;
      }

      // populate the ancestry array for the latest deepest node
      deepestNodeParents = deepestNodeParents.length ? deepestNodeParents : getNodeParents(deepestNode);
      var ancestryStart = void 0;

      // if the deepest node is an HTMLElement and the current node is a non root svg element
      if (deepestNode instanceof domObjects$1.HTMLElement && currentNode instanceof domObjects$1.SVGElement && !(currentNode instanceof domObjects$1.SVGSVGElement)) {
        // TODO: is this check necessary? Was this for HTML elements embedded in SVG?
        if (currentNode === deepestNodeParent) {
          continue;
        }
        ancestryStart = currentNode.ownerSVGElement;
      } else {
        ancestryStart = currentNode;
      }
      var currentNodeParents = getNodeParents(ancestryStart, deepestNode.ownerDocument);
      var commonIndex = 0;

      // get (position of closest common ancestor) + 1
      while (currentNodeParents[commonIndex] && currentNodeParents[commonIndex] === deepestNodeParents[commonIndex]) {
        commonIndex++;
      }
      var parents = [currentNodeParents[commonIndex - 1], currentNodeParents[commonIndex], deepestNodeParents[commonIndex]];
      if (parents[0]) {
        var child = parents[0].lastChild;
        while (child) {
          if (child === parents[1]) {
            deepestNodeIndex = i;
            deepestNodeParents = currentNodeParents;
            break;
          } else if (child === parents[2]) {
            break;
          }
          child = child.previousSibling;
        }
      }
    }
    return deepestNodeIndex;
  }
  function getNodeParents(node, limit) {
    var parents = [];
    var parent = node;
    var parentParent;
    while ((parentParent = getParent(parent)) && parent !== limit && parentParent !== parent.ownerDocument) {
      parents.unshift(parent);
      parent = parentParent;
    }
    return parents;
  }
  function zIndexIsHigherThan(higherNode, lowerNode) {
    var higherIndex = parseInt(getWindow(higherNode).getComputedStyle(higherNode).zIndex, 10) || 0;
    var lowerIndex = parseInt(getWindow(lowerNode).getComputedStyle(lowerNode).zIndex, 10) || 0;
    return higherIndex >= lowerIndex;
  }
  function matchesUpTo(element, selector, limit) {
    while (is.element(element)) {
      if (matchesSelector(element, selector)) {
        return true;
      }
      element = parentNode(element);
      if (element === limit) {
        return matchesSelector(element, selector);
      }
    }
    return false;
  }
  function getActualElement(element) {
    return element.correspondingUseElement || element;
  }
  function getScrollXY(relevantWindow) {
    relevantWindow = relevantWindow || win;
    return {
      x: relevantWindow.scrollX || relevantWindow.document.documentElement.scrollLeft,
      y: relevantWindow.scrollY || relevantWindow.document.documentElement.scrollTop
    };
  }
  function getElementClientRect(element) {
    var clientRect = element instanceof domObjects$1.SVGElement ? element.getBoundingClientRect() : element.getClientRects()[0];
    return clientRect && {
      left: clientRect.left,
      right: clientRect.right,
      top: clientRect.top,
      bottom: clientRect.bottom,
      width: clientRect.width || clientRect.right - clientRect.left,
      height: clientRect.height || clientRect.bottom - clientRect.top
    };
  }
  function getElementRect(element) {
    var clientRect = getElementClientRect(element);
    if (!browser$1.isIOS7 && clientRect) {
      var scroll = getScrollXY(getWindow(element));
      clientRect.left += scroll.x;
      clientRect.right += scroll.x;
      clientRect.top += scroll.y;
      clientRect.bottom += scroll.y;
    }
    return clientRect;
  }
  function getPath(node) {
    var path = [];
    while (node) {
      path.push(node);
      node = parentNode(node);
    }
    return path;
  }
  function trySelector(value) {
    if (!is.string(value)) {
      return false;
    }

    // an exception will be raised if it is invalid
    domObjects$1.document.querySelector(value);
    return true;
  }

  function extend(dest, source) {
    for (var prop in source) {
      dest[prop] = source[prop];
    }
    var ret = dest;
    return ret;
  }

  function getStringOptionResult(value, target, element) {
    if (value === 'parent') {
      return parentNode(element);
    }
    if (value === 'self') {
      return target.getRect(element);
    }
    return closest(element, value);
  }
  function resolveRectLike(value, target, element, functionArgs) {
    var returnValue = value;
    if (is.string(returnValue)) {
      returnValue = getStringOptionResult(returnValue, target, element);
    } else if (is.func(returnValue)) {
      returnValue = returnValue.apply(void 0, functionArgs);
    }
    if (is.element(returnValue)) {
      returnValue = getElementRect(returnValue);
    }
    return returnValue;
  }
  function rectToXY(rect) {
    return rect && {
      x: 'x' in rect ? rect.x : rect.left,
      y: 'y' in rect ? rect.y : rect.top
    };
  }
  function xywhToTlbr(rect) {
    if (rect && !('left' in rect && 'top' in rect)) {
      rect = extend({}, rect);
      rect.left = rect.x || 0;
      rect.top = rect.y || 0;
      rect.right = rect.right || rect.left + rect.width;
      rect.bottom = rect.bottom || rect.top + rect.height;
    }
    return rect;
  }
  function tlbrToXywh(rect) {
    if (rect && !('x' in rect && 'y' in rect)) {
      rect = extend({}, rect);
      rect.x = rect.left || 0;
      rect.y = rect.top || 0;
      rect.width = rect.width || (rect.right || 0) - rect.x;
      rect.height = rect.height || (rect.bottom || 0) - rect.y;
    }
    return rect;
  }
  function addEdges(edges, rect, delta) {
    if (edges.left) {
      rect.left += delta.x;
    }
    if (edges.right) {
      rect.right += delta.x;
    }
    if (edges.top) {
      rect.top += delta.y;
    }
    if (edges.bottom) {
      rect.bottom += delta.y;
    }
    rect.width = rect.right - rect.left;
    rect.height = rect.bottom - rect.top;
  }

  function getOriginXY(target, element, actionName) {
    var actionOptions = actionName && target.options[actionName];
    var actionOrigin = actionOptions && actionOptions.origin;
    var origin = actionOrigin || target.options.origin;
    var originRect = resolveRectLike(origin, target, element, [target && element]);
    return rectToXY(originRect) || {
      x: 0,
      y: 0
    };
  }

  function normalize(type, listeners) {
    var filter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function (_typeOrPrefix) {
      return true;
    };
    var result = arguments.length > 3 ? arguments[3] : undefined;
    result = result || {};
    if (is.string(type) && type.search(' ') !== -1) {
      type = split(type);
    }
    if (is.array(type)) {
      type.forEach(function (t) {
        return normalize(t, listeners, filter, result);
      });
      return result;
    }

    // before:  type = [{ drag: () => {} }], listeners = undefined
    // after:   type = ''                  , listeners = [{ drag: () => {} }]
    if (is.object(type)) {
      listeners = type;
      type = '';
    }
    if (is.func(listeners) && filter(type)) {
      result[type] = result[type] || [];
      result[type].push(listeners);
    } else if (is.array(listeners)) {
      for (var _i2 = 0, _listeners2 = listeners; _i2 < _listeners2.length; _i2++) {
        var l = _listeners2[_i2];
        normalize(type, l, filter, result);
      }
    } else if (is.object(listeners)) {
      for (var prefix in listeners) {
        var combinedTypes = split(prefix).map(function (p) {
          return "".concat(type).concat(p);
        });
        normalize(combinedTypes, listeners[prefix], filter, result);
      }
    }
    return result;
  }
  function split(type) {
    return type.trim().split(/ +/);
  }

  var hypot = (function (x, y) {
    return Math.sqrt(x * x + y * y);
  });

  var VENDOR_PREFIXES = ['webkit', 'moz'];
  function pointerExtend(dest, source) {
    dest.__set || (dest.__set = {});
    var _loop = function _loop(prop) {
      // skip deprecated prefixed properties
      if (VENDOR_PREFIXES.some(function (prefix) {
        return prop.indexOf(prefix) === 0;
      })) return 1; // continue
      if (typeof dest[prop] !== 'function' && prop !== '__set') {
        Object.defineProperty(dest, prop, {
          get: function get() {
            if (prop in dest.__set) return dest.__set[prop];
            return dest.__set[prop] = source[prop];
          },
          set: function set(value) {
            dest.__set[prop] = value;
          },
          configurable: true
        });
      }
    };
    for (var prop in source) {
      if (_loop(prop)) continue;
    }
    return dest;
  }

  function copyCoords(dest, src) {
    dest.page = dest.page || {};
    dest.page.x = src.page.x;
    dest.page.y = src.page.y;
    dest.client = dest.client || {};
    dest.client.x = src.client.x;
    dest.client.y = src.client.y;
    dest.timeStamp = src.timeStamp;
  }
  function setCoordDeltas(targetObj, prev, cur) {
    targetObj.page.x = cur.page.x - prev.page.x;
    targetObj.page.y = cur.page.y - prev.page.y;
    targetObj.client.x = cur.client.x - prev.client.x;
    targetObj.client.y = cur.client.y - prev.client.y;
    targetObj.timeStamp = cur.timeStamp - prev.timeStamp;
  }
  function setCoordVelocity(targetObj, delta) {
    var dt = Math.max(delta.timeStamp / 1000, 0.001);
    targetObj.page.x = delta.page.x / dt;
    targetObj.page.y = delta.page.y / dt;
    targetObj.client.x = delta.client.x / dt;
    targetObj.client.y = delta.client.y / dt;
    targetObj.timeStamp = dt;
  }
  function setZeroCoords(targetObj) {
    targetObj.page.x = 0;
    targetObj.page.y = 0;
    targetObj.client.x = 0;
    targetObj.client.y = 0;
  }
  function isNativePointer(pointer) {
    return pointer instanceof domObjects$1.Event || pointer instanceof domObjects$1.Touch;
  }

  // Get specified X/Y coords for mouse or event.touches[0]
  function getXY(type, pointer, xy) {
    xy = xy || {};
    type = type || 'page';
    xy.x = pointer[type + 'X'];
    xy.y = pointer[type + 'Y'];
    return xy;
  }
  function getPageXY(pointer, page) {
    page = page || {
      x: 0,
      y: 0
    };

    // Opera Mobile handles the viewport and scrolling oddly
    if (browser$1.isOperaMobile && isNativePointer(pointer)) {
      getXY('screen', pointer, page);
      page.x += window.scrollX;
      page.y += window.scrollY;
    } else {
      getXY('page', pointer, page);
    }
    return page;
  }
  function getClientXY(pointer, client) {
    client = client || {};
    if (browser$1.isOperaMobile && isNativePointer(pointer)) {
      // Opera Mobile handles the viewport and scrolling oddly
      getXY('screen', pointer, client);
    } else {
      getXY('client', pointer, client);
    }
    return client;
  }
  function getPointerId(pointer) {
    return is.number(pointer.pointerId) ? pointer.pointerId : pointer.identifier;
  }
  function setCoords(dest, pointers, timeStamp) {
    var pointer = pointers.length > 1 ? pointerAverage(pointers) : pointers[0];
    getPageXY(pointer, dest.page);
    getClientXY(pointer, dest.client);
    dest.timeStamp = timeStamp;
  }
  function getTouchPair(event) {
    var touches = [];

    // array of touches is supplied
    if (is.array(event)) {
      touches[0] = event[0];
      touches[1] = event[1];
    }
    // an event
    else {
      if (event.type === 'touchend') {
        if (event.touches.length === 1) {
          touches[0] = event.touches[0];
          touches[1] = event.changedTouches[0];
        } else if (event.touches.length === 0) {
          touches[0] = event.changedTouches[0];
          touches[1] = event.changedTouches[1];
        }
      } else {
        touches[0] = event.touches[0];
        touches[1] = event.touches[1];
      }
    }
    return touches;
  }
  function pointerAverage(pointers) {
    var average = {
      pageX: 0,
      pageY: 0,
      clientX: 0,
      clientY: 0,
      screenX: 0,
      screenY: 0
    };
    for (var _i2 = 0; _i2 < pointers.length; _i2++) {
      var pointer = pointers[_i2];
      for (var prop in average) {
        average[prop] += pointer[prop];
      }
    }
    for (var _prop in average) {
      average[_prop] /= pointers.length;
    }
    return average;
  }
  function touchBBox(event) {
    if (!event.length) {
      return null;
    }
    var touches = getTouchPair(event);
    var minX = Math.min(touches[0].pageX, touches[1].pageX);
    var minY = Math.min(touches[0].pageY, touches[1].pageY);
    var maxX = Math.max(touches[0].pageX, touches[1].pageX);
    var maxY = Math.max(touches[0].pageY, touches[1].pageY);
    return {
      x: minX,
      y: minY,
      left: minX,
      top: minY,
      right: maxX,
      bottom: maxY,
      width: maxX - minX,
      height: maxY - minY
    };
  }
  function touchDistance(event, deltaSource) {
    var sourceX = deltaSource + 'X';
    var sourceY = deltaSource + 'Y';
    var touches = getTouchPair(event);
    var dx = touches[0][sourceX] - touches[1][sourceX];
    var dy = touches[0][sourceY] - touches[1][sourceY];
    return hypot(dx, dy);
  }
  function touchAngle(event, deltaSource) {
    var sourceX = deltaSource + 'X';
    var sourceY = deltaSource + 'Y';
    var touches = getTouchPair(event);
    var dx = touches[1][sourceX] - touches[0][sourceX];
    var dy = touches[1][sourceY] - touches[0][sourceY];
    var angle = 180 * Math.atan2(dy, dx) / Math.PI;
    return angle;
  }
  function getPointerType(pointer) {
    return is.string(pointer.pointerType) ? pointer.pointerType : is.number(pointer.pointerType) ? [undefined, undefined, 'touch', 'pen', 'mouse'][pointer.pointerType] :
    // if the PointerEvent API isn't available, then the "pointer" must
    // be either a MouseEvent, TouchEvent, or Touch object
    /touch/.test(pointer.type || '') || pointer instanceof domObjects$1.Touch ? 'touch' : 'mouse';
  }

  // [ event.target, event.currentTarget ]
  function getEventTargets(event) {
    var path = is.func(event.composedPath) ? event.composedPath() : event.path;
    return [getActualElement(path ? path[0] : event.target), getActualElement(event.currentTarget)];
  }
  function newCoords() {
    return {
      page: {
        x: 0,
        y: 0
      },
      client: {
        x: 0,
        y: 0
      },
      timeStamp: 0
    };
  }
  function coordsToEvent(coords) {
    var event = {
      coords: coords,
      get page() {
        return this.coords.page;
      },
      get client() {
        return this.coords.client;
      },
      get timeStamp() {
        return this.coords.timeStamp;
      },
      get pageX() {
        return this.coords.page.x;
      },
      get pageY() {
        return this.coords.page.y;
      },
      get clientX() {
        return this.coords.client.x;
      },
      get clientY() {
        return this.coords.client.y;
      },
      get pointerId() {
        return this.coords.pointerId;
      },
      get target() {
        return this.coords.target;
      },
      get type() {
        return this.coords.type;
      },
      get pointerType() {
        return this.coords.pointerType;
      },
      get buttons() {
        return this.coords.buttons;
      },
      preventDefault: function preventDefault() {}
    };
    return event;
  }

  var BaseEvent = /*#__PURE__*/function () {
    function BaseEvent(interaction) {
      _classCallCheck(this, BaseEvent);
      /** @internal */
      this.immediatePropagationStopped = false;
      this.propagationStopped = false;
      this._interaction = interaction;
    }
    _createClass(BaseEvent, [{
      key: "preventDefault",
      value: function preventDefault() {}

      /**
       * Don't call any other listeners (even on the current target)
       */
    }, {
      key: "stopPropagation",
      value: function stopPropagation() {
        this.propagationStopped = true;
      }

      /**
       * Don't call listeners on the remaining targets
       */
    }, {
      key: "stopImmediatePropagation",
      value: function stopImmediatePropagation() {
        this.immediatePropagationStopped = this.propagationStopped = true;
      }
    }]);
    return BaseEvent;
  }();

  // defined outside of class definition to avoid assignment of undefined during
  // construction

  // getters and setters defined here to support typescript 3.6 and below which
  // don't support getter and setters in .d.ts files
  Object.defineProperty(BaseEvent.prototype, 'interaction', {
    get: function get() {
      return this._interaction._proxy;
    },
    set: function set() {}
  });

  var remove = function remove(array, target) {
    return array.splice(array.indexOf(target), 1);
  };
  var merge = function merge(target, source) {
    for (var _i2 = 0; _i2 < source.length; _i2++) {
      var item = source[_i2];
      target.push(item);
    }
    return target;
  };
  var from = function from(source) {
    return merge([], source);
  };
  var findIndex = function findIndex(array, func) {
    for (var i = 0; i < array.length; i++) {
      if (func(array[i], i, array)) {
        return i;
      }
    }
    return -1;
  };
  var find = function find(array, func) {
    return array[findIndex(array, func)];
  };

  var DropEvent = /*#__PURE__*/function (_BaseEvent) {
    _inherits(DropEvent, _BaseEvent);
    var _super = _createSuper(DropEvent);
    /**
     * Class of events fired on dropzones during drags with acceptable targets.
     */
    function DropEvent(dropState, dragEvent, type) {
      var _this;
      _classCallCheck(this, DropEvent);
      _this = _super.call(this, dragEvent._interaction);
      _this.dropzone = void 0;
      _this.dragEvent = void 0;
      _this.relatedTarget = void 0;
      _this.draggable = void 0;
      _this.propagationStopped = false;
      _this.immediatePropagationStopped = false;
      var _ref = type === 'dragleave' ? dropState.prev : dropState.cur,
        element = _ref.element,
        dropzone = _ref.dropzone;
      _this.type = type;
      _this.target = element;
      _this.currentTarget = element;
      _this.dropzone = dropzone;
      _this.dragEvent = dragEvent;
      _this.relatedTarget = dragEvent.target;
      _this.draggable = dragEvent.interactable;
      _this.timeStamp = dragEvent.timeStamp;
      return _this;
    }

    /**
     * If this is a `dropactivate` event, the dropzone element will be
     * deactivated.
     *
     * If this is a `dragmove` or `dragenter`, a `dragleave` will be fired on the
     * dropzone element and more.
     */
    _createClass(DropEvent, [{
      key: "reject",
      value: function reject() {
        var _this2 = this;
        var dropState = this._interaction.dropState;
        if (this.type !== 'dropactivate' && (!this.dropzone || dropState.cur.dropzone !== this.dropzone || dropState.cur.element !== this.target)) {
          return;
        }
        dropState.prev.dropzone = this.dropzone;
        dropState.prev.element = this.target;
        dropState.rejected = true;
        dropState.events.enter = null;
        this.stopImmediatePropagation();
        if (this.type === 'dropactivate') {
          var activeDrops = dropState.activeDrops;
          var index = findIndex(activeDrops, function (_ref2) {
            var dropzone = _ref2.dropzone,
              element = _ref2.element;
            return dropzone === _this2.dropzone && element === _this2.target;
          });
          dropState.activeDrops.splice(index, 1);
          var deactivateEvent = new DropEvent(dropState, this.dragEvent, 'dropdeactivate');
          deactivateEvent.dropzone = this.dropzone;
          deactivateEvent.target = this.target;
          this.dropzone.fire(deactivateEvent);
        } else {
          this.dropzone.fire(new DropEvent(dropState, this.dragEvent, 'dragleave'));
        }
      }
    }, {
      key: "preventDefault",
      value: function preventDefault() {}
    }, {
      key: "stopPropagation",
      value: function stopPropagation() {
        this.propagationStopped = true;
      }
    }, {
      key: "stopImmediatePropagation",
      value: function stopImmediatePropagation() {
        this.immediatePropagationStopped = this.propagationStopped = true;
      }
    }]);
    return DropEvent;
  }(BaseEvent);

  function install$f(scope) {
    var actions = scope.actions,
      interact = scope.interactStatic,
      Interactable = scope.Interactable,
      defaults = scope.defaults;
    scope.usePlugin(drag$1);
    Interactable.prototype.dropzone = function (options) {
      return dropzoneMethod(this, options);
    };
    Interactable.prototype.dropCheck = function (dragEvent, event, draggable, draggableElement, dropElement, rect) {
      return dropCheckMethod(this, dragEvent, event, draggable, draggableElement, dropElement, rect);
    };
    interact.dynamicDrop = function (newValue) {
      if (is.bool(newValue)) {
        // if (dragging && scope.dynamicDrop !== newValue && !newValue) {
        //  calcRects(dropzones)
        // }

        scope.dynamicDrop = newValue;
        return interact;
      }
      return scope.dynamicDrop;
    };
    extend(actions.phaselessTypes, {
      dragenter: true,
      dragleave: true,
      dropactivate: true,
      dropdeactivate: true,
      dropmove: true,
      drop: true
    });
    actions.methodDict.drop = 'dropzone';
    scope.dynamicDrop = false;
    defaults.actions.drop = drop.defaults;
  }
  function collectDropzones(_ref, draggableElement) {
    var interactables = _ref.interactables;
    var drops = [];

    // collect all dropzones and their elements which qualify for a drop
    for (var _i2 = 0, _interactables$list2 = interactables.list; _i2 < _interactables$list2.length; _i2++) {
      var _dropzone = _interactables$list2[_i2];
      if (!_dropzone.options.drop.enabled) {
        continue;
      }
      var accept = _dropzone.options.drop.accept;

      // test the draggable draggableElement against the dropzone's accept setting
      if (is.element(accept) && accept !== draggableElement || is.string(accept) && !matchesSelector(draggableElement, accept) || is.func(accept) && !accept({
        dropzone: _dropzone,
        draggableElement: draggableElement
      })) {
        continue;
      }
      for (var _i4 = 0, _dropzone$getAllEleme2 = _dropzone.getAllElements(); _i4 < _dropzone$getAllEleme2.length; _i4++) {
        var dropzoneElement = _dropzone$getAllEleme2[_i4];
        if (dropzoneElement !== draggableElement) {
          drops.push({
            dropzone: _dropzone,
            element: dropzoneElement,
            rect: _dropzone.getRect(dropzoneElement)
          });
        }
      }
    }
    return drops;
  }
  function fireActivationEvents(activeDrops, event) {
    // loop through all active dropzones and trigger event
    for (var _i6 = 0, _activeDrops$slice2 = activeDrops.slice(); _i6 < _activeDrops$slice2.length; _i6++) {
      var _activeDrops$slice2$_ = _activeDrops$slice2[_i6],
        _dropzone2 = _activeDrops$slice2$_.dropzone,
        element = _activeDrops$slice2$_.element;
      event.dropzone = _dropzone2;

      // set current element as event target
      event.target = element;
      _dropzone2.fire(event);
      event.propagationStopped = event.immediatePropagationStopped = false;
    }
  }

  // return a new array of possible drops. getActiveDrops should always be
  // called when a drag has just started or a drag event happens while
  // dynamicDrop is true
  function getActiveDrops(scope, dragElement) {
    // get dropzones and their elements that could receive the draggable
    var activeDrops = collectDropzones(scope, dragElement);
    for (var _i8 = 0; _i8 < activeDrops.length; _i8++) {
      var activeDrop = activeDrops[_i8];
      activeDrop.rect = activeDrop.dropzone.getRect(activeDrop.element);
    }
    return activeDrops;
  }
  function getDrop(_ref2, dragEvent, pointerEvent) {
    var dropState = _ref2.dropState,
      draggable = _ref2.interactable,
      dragElement = _ref2.element;
    var validDrops = [];

    // collect all dropzones and their elements which qualify for a drop
    for (var _i10 = 0, _dropState$activeDrop2 = dropState.activeDrops; _i10 < _dropState$activeDrop2.length; _i10++) {
      var _dropState$activeDrop3 = _dropState$activeDrop2[_i10],
        _dropzone3 = _dropState$activeDrop3.dropzone,
        dropzoneElement = _dropState$activeDrop3.element,
        _rect = _dropState$activeDrop3.rect;
      var isValid = _dropzone3.dropCheck(dragEvent, pointerEvent, draggable, dragElement, dropzoneElement, _rect);
      validDrops.push(isValid ? dropzoneElement : null);
    } // get the most appropriate dropzone based on DOM depth and order
    var dropIndex = indexOfDeepestElement(validDrops);
    return dropState.activeDrops[dropIndex] || null;
  }
  function getDropEvents(interaction, _pointerEvent, dragEvent) {
    var dropState = interaction.dropState;
    var dropEvents = {
      enter: null,
      leave: null,
      activate: null,
      deactivate: null,
      move: null,
      drop: null
    };
    if (dragEvent.type === 'dragstart') {
      dropEvents.activate = new DropEvent(dropState, dragEvent, 'dropactivate');
      dropEvents.activate.target = null;
      dropEvents.activate.dropzone = null;
    }
    if (dragEvent.type === 'dragend') {
      dropEvents.deactivate = new DropEvent(dropState, dragEvent, 'dropdeactivate');
      dropEvents.deactivate.target = null;
      dropEvents.deactivate.dropzone = null;
    }
    if (dropState.rejected) {
      return dropEvents;
    }
    if (dropState.cur.element !== dropState.prev.element) {
      // if there was a previous dropzone, create a dragleave event
      if (dropState.prev.dropzone) {
        dropEvents.leave = new DropEvent(dropState, dragEvent, 'dragleave');
        dragEvent.dragLeave = dropEvents.leave.target = dropState.prev.element;
        dragEvent.prevDropzone = dropEvents.leave.dropzone = dropState.prev.dropzone;
      }
      // if dropzone is not null, create a dragenter event
      if (dropState.cur.dropzone) {
        dropEvents.enter = new DropEvent(dropState, dragEvent, 'dragenter');
        dragEvent.dragEnter = dropState.cur.element;
        dragEvent.dropzone = dropState.cur.dropzone;
      }
    }
    if (dragEvent.type === 'dragend' && dropState.cur.dropzone) {
      dropEvents.drop = new DropEvent(dropState, dragEvent, 'drop');
      dragEvent.dropzone = dropState.cur.dropzone;
      dragEvent.relatedTarget = dropState.cur.element;
    }
    if (dragEvent.type === 'dragmove' && dropState.cur.dropzone) {
      dropEvents.move = new DropEvent(dropState, dragEvent, 'dropmove');
      dragEvent.dropzone = dropState.cur.dropzone;
    }
    return dropEvents;
  }
  function fireDropEvents(interaction, events) {
    var dropState = interaction.dropState;
    var activeDrops = dropState.activeDrops,
      cur = dropState.cur,
      prev = dropState.prev;
    if (events.leave) {
      prev.dropzone.fire(events.leave);
    }
    if (events.enter) {
      cur.dropzone.fire(events.enter);
    }
    if (events.move) {
      cur.dropzone.fire(events.move);
    }
    if (events.drop) {
      cur.dropzone.fire(events.drop);
    }
    if (events.deactivate) {
      fireActivationEvents(activeDrops, events.deactivate);
    }
    dropState.prev.dropzone = cur.dropzone;
    dropState.prev.element = cur.element;
  }
  function onEventCreated(_ref3, scope) {
    var interaction = _ref3.interaction,
      iEvent = _ref3.iEvent,
      event = _ref3.event;
    if (iEvent.type !== 'dragmove' && iEvent.type !== 'dragend') {
      return;
    }
    var dropState = interaction.dropState;
    if (scope.dynamicDrop) {
      dropState.activeDrops = getActiveDrops(scope, interaction.element);
    }
    var dragEvent = iEvent;
    var dropResult = getDrop(interaction, dragEvent, event);

    // update rejected status
    dropState.rejected = dropState.rejected && !!dropResult && dropResult.dropzone === dropState.cur.dropzone && dropResult.element === dropState.cur.element;
    dropState.cur.dropzone = dropResult && dropResult.dropzone;
    dropState.cur.element = dropResult && dropResult.element;
    dropState.events = getDropEvents(interaction, event, dragEvent);
  }
  function dropzoneMethod(interactable, options) {
    if (is.object(options)) {
      interactable.options.drop.enabled = options.enabled !== false;
      if (options.listeners) {
        var normalized = normalize(options.listeners);
        // rename 'drop' to '' as it will be prefixed with 'drop'
        var corrected = Object.keys(normalized).reduce(function (acc, type) {
          var correctedType = /^(enter|leave)/.test(type) ? "drag".concat(type) : /^(activate|deactivate|move)/.test(type) ? "drop".concat(type) : type;
          acc[correctedType] = normalized[type];
          return acc;
        }, {});
        var prevListeners = interactable.options.drop.listeners;
        prevListeners && interactable.off(prevListeners);
        interactable.on(corrected);
        interactable.options.drop.listeners = corrected;
      }
      if (is.func(options.ondrop)) {
        interactable.on('drop', options.ondrop);
      }
      if (is.func(options.ondropactivate)) {
        interactable.on('dropactivate', options.ondropactivate);
      }
      if (is.func(options.ondropdeactivate)) {
        interactable.on('dropdeactivate', options.ondropdeactivate);
      }
      if (is.func(options.ondragenter)) {
        interactable.on('dragenter', options.ondragenter);
      }
      if (is.func(options.ondragleave)) {
        interactable.on('dragleave', options.ondragleave);
      }
      if (is.func(options.ondropmove)) {
        interactable.on('dropmove', options.ondropmove);
      }
      if (/^(pointer|center)$/.test(options.overlap)) {
        interactable.options.drop.overlap = options.overlap;
      } else if (is.number(options.overlap)) {
        interactable.options.drop.overlap = Math.max(Math.min(1, options.overlap), 0);
      }
      if ('accept' in options) {
        interactable.options.drop.accept = options.accept;
      }
      if ('checker' in options) {
        interactable.options.drop.checker = options.checker;
      }
      return interactable;
    }
    if (is.bool(options)) {
      interactable.options.drop.enabled = options;
      return interactable;
    }
    return interactable.options.drop;
  }
  function dropCheckMethod(interactable, dragEvent, event, draggable, draggableElement, dropElement, rect) {
    var dropped = false;

    // if the dropzone has no rect (eg. display: none)
    // call the custom dropChecker or just return false
    if (!(rect = rect || interactable.getRect(dropElement))) {
      return interactable.options.drop.checker ? interactable.options.drop.checker(dragEvent, event, dropped, interactable, dropElement, draggable, draggableElement) : false;
    }
    var dropOverlap = interactable.options.drop.overlap;
    if (dropOverlap === 'pointer') {
      var origin = getOriginXY(draggable, draggableElement, 'drag');
      var page = getPageXY(dragEvent);
      page.x += origin.x;
      page.y += origin.y;
      var horizontal = page.x > rect.left && page.x < rect.right;
      var vertical = page.y > rect.top && page.y < rect.bottom;
      dropped = horizontal && vertical;
    }
    var dragRect = draggable.getRect(draggableElement);
    if (dragRect && dropOverlap === 'center') {
      var cx = dragRect.left + dragRect.width / 2;
      var cy = dragRect.top + dragRect.height / 2;
      dropped = cx >= rect.left && cx <= rect.right && cy >= rect.top && cy <= rect.bottom;
    }
    if (dragRect && is.number(dropOverlap)) {
      var overlapArea = Math.max(0, Math.min(rect.right, dragRect.right) - Math.max(rect.left, dragRect.left)) * Math.max(0, Math.min(rect.bottom, dragRect.bottom) - Math.max(rect.top, dragRect.top));
      var overlapRatio = overlapArea / (dragRect.width * dragRect.height);
      dropped = overlapRatio >= dropOverlap;
    }
    if (interactable.options.drop.checker) {
      dropped = interactable.options.drop.checker(dragEvent, event, dropped, interactable, dropElement, draggable, draggableElement);
    }
    return dropped;
  }
  var drop = {
    id: 'actions/drop',
    install: install$f,
    listeners: {
      'interactions:before-action-start': function interactionsBeforeActionStart(_ref4) {
        var interaction = _ref4.interaction;
        if (interaction.prepared.name !== 'drag') {
          return;
        }
        interaction.dropState = {
          cur: {
            dropzone: null,
            element: null
          },
          prev: {
            dropzone: null,
            element: null
          },
          rejected: null,
          events: null,
          activeDrops: []
        };
      },
      'interactions:after-action-start': function interactionsAfterActionStart(_ref5, scope) {
        var interaction = _ref5.interaction,
          event = _ref5.event,
          dragEvent = _ref5.iEvent;
        if (interaction.prepared.name !== 'drag') {
          return;
        }
        var dropState = interaction.dropState;

        // reset active dropzones
        dropState.activeDrops = [];
        dropState.events = {};
        dropState.activeDrops = getActiveDrops(scope, interaction.element);
        dropState.events = getDropEvents(interaction, event, dragEvent);
        if (dropState.events.activate) {
          fireActivationEvents(dropState.activeDrops, dropState.events.activate);
          scope.fire('actions/drop:start', {
            interaction: interaction,
            dragEvent: dragEvent
          });
        }
      },
      'interactions:action-move': onEventCreated,
      'interactions:after-action-move': function interactionsAfterActionMove(_ref6, scope) {
        var interaction = _ref6.interaction,
          dragEvent = _ref6.iEvent;
        if (interaction.prepared.name !== 'drag') {
          return;
        }
        var dropState = interaction.dropState;
        fireDropEvents(interaction, dropState.events);
        scope.fire('actions/drop:move', {
          interaction: interaction,
          dragEvent: dragEvent
        });
        dropState.events = {};
      },
      'interactions:action-end': function interactionsActionEnd(arg, scope) {
        if (arg.interaction.prepared.name !== 'drag') {
          return;
        }
        var interaction = arg.interaction,
          dragEvent = arg.iEvent;
        onEventCreated(arg, scope);
        fireDropEvents(interaction, interaction.dropState.events);
        scope.fire('actions/drop:end', {
          interaction: interaction,
          dragEvent: dragEvent
        });
      },
      'interactions:stop': function interactionsStop(_ref7) {
        var interaction = _ref7.interaction;
        if (interaction.prepared.name !== 'drag') {
          return;
        }
        var dropState = interaction.dropState;
        if (dropState) {
          dropState.activeDrops = null;
          dropState.events = null;
          dropState.cur.dropzone = null;
          dropState.cur.element = null;
          dropState.prev.dropzone = null;
          dropState.prev.element = null;
          dropState.rejected = false;
        }
      }
    },
    getActiveDrops: getActiveDrops,
    getDrop: getDrop,
    getDropEvents: getDropEvents,
    fireDropEvents: fireDropEvents,
    filterEventType: function filterEventType(type) {
      return type.search('drag') === 0 || type.search('drop') === 0;
    },
    defaults: {
      enabled: false,
      accept: null,
      overlap: 'pointer'
    }
  };
  var drop$1 = drop;

  function install$e(scope) {
    var actions = scope.actions,
      Interactable = scope.Interactable,
      defaults = scope.defaults;
    Interactable.prototype.gesturable = function (options) {
      if (is.object(options)) {
        this.options.gesture.enabled = options.enabled !== false;
        this.setPerAction('gesture', options);
        this.setOnEvents('gesture', options);
        return this;
      }
      if (is.bool(options)) {
        this.options.gesture.enabled = options;
        return this;
      }
      return this.options.gesture;
    };
    actions.map.gesture = gesture;
    actions.methodDict.gesture = 'gesturable';
    defaults.actions.gesture = gesture.defaults;
  }
  function updateGestureProps(_ref) {
    var interaction = _ref.interaction,
      iEvent = _ref.iEvent,
      phase = _ref.phase;
    if (interaction.prepared.name !== 'gesture') return;
    var pointers = interaction.pointers.map(function (p) {
      return p.pointer;
    });
    var starting = phase === 'start';
    var ending = phase === 'end';
    var deltaSource = interaction.interactable.options.deltaSource;
    iEvent.touches = [pointers[0], pointers[1]];
    if (starting) {
      iEvent.distance = touchDistance(pointers, deltaSource);
      iEvent.box = touchBBox(pointers);
      iEvent.scale = 1;
      iEvent.ds = 0;
      iEvent.angle = touchAngle(pointers, deltaSource);
      iEvent.da = 0;
      interaction.gesture.startDistance = iEvent.distance;
      interaction.gesture.startAngle = iEvent.angle;
    } else if (ending || interaction.pointers.length < 2) {
      var prevEvent = interaction.prevEvent;
      iEvent.distance = prevEvent.distance;
      iEvent.box = prevEvent.box;
      iEvent.scale = prevEvent.scale;
      iEvent.ds = 0;
      iEvent.angle = prevEvent.angle;
      iEvent.da = 0;
    } else {
      iEvent.distance = touchDistance(pointers, deltaSource);
      iEvent.box = touchBBox(pointers);
      iEvent.scale = iEvent.distance / interaction.gesture.startDistance;
      iEvent.angle = touchAngle(pointers, deltaSource);
      iEvent.ds = iEvent.scale - interaction.gesture.scale;
      iEvent.da = iEvent.angle - interaction.gesture.angle;
    }
    interaction.gesture.distance = iEvent.distance;
    interaction.gesture.angle = iEvent.angle;
    if (is.number(iEvent.scale) && iEvent.scale !== Infinity && !isNaN(iEvent.scale)) {
      interaction.gesture.scale = iEvent.scale;
    }
  }
  var gesture = {
    id: 'actions/gesture',
    before: ['actions/drag', 'actions/resize'],
    install: install$e,
    listeners: {
      'interactions:action-start': updateGestureProps,
      'interactions:action-move': updateGestureProps,
      'interactions:action-end': updateGestureProps,
      'interactions:new': function interactionsNew(_ref2) {
        var interaction = _ref2.interaction;
        interaction.gesture = {
          angle: 0,
          distance: 0,
          scale: 1,
          startAngle: 0,
          startDistance: 0
        };
      },
      'auto-start:check': function autoStartCheck(arg) {
        if (arg.interaction.pointers.length < 2) {
          return undefined;
        }
        var gestureOptions = arg.interactable.options.gesture;
        if (!(gestureOptions && gestureOptions.enabled)) {
          return undefined;
        }
        arg.action = {
          name: 'gesture'
        };
        return false;
      }
    },
    defaults: {},
    getCursor: function getCursor() {
      return '';
    },
    filterEventType: function filterEventType(type) {
      return type.search('gesture') === 0;
    }
  };
  var gesture$1 = gesture;

  function install$d(scope) {
    var actions = scope.actions,
      browser = scope.browser,
      Interactable = scope.Interactable,
      defaults = scope.defaults;

    // Less Precision with touch input

    resize.cursors = initCursors(browser);
    resize.defaultMargin = browser.supportsTouch || browser.supportsPointerEvent ? 20 : 10;
    Interactable.prototype.resizable = function (options) {
      return resizable(this, options, scope);
    };
    actions.map.resize = resize;
    actions.methodDict.resize = 'resizable';
    defaults.actions.resize = resize.defaults;
  }
  function resizeChecker(arg) {
    var interaction = arg.interaction,
      interactable = arg.interactable,
      element = arg.element,
      rect = arg.rect,
      buttons = arg.buttons;
    if (!rect) {
      return undefined;
    }
    var page = extend({}, interaction.coords.cur.page);
    var resizeOptions = interactable.options.resize;
    if (!(resizeOptions && resizeOptions.enabled) ||
    // check mouseButton setting if the pointer is down
    interaction.pointerIsDown && /mouse|pointer/.test(interaction.pointerType) && (buttons & resizeOptions.mouseButtons) === 0) {
      return undefined;
    }

    // if using resize.edges
    if (is.object(resizeOptions.edges)) {
      var resizeEdges = {
        left: false,
        right: false,
        top: false,
        bottom: false
      };
      for (var edge in resizeEdges) {
        resizeEdges[edge] = checkResizeEdge(edge, resizeOptions.edges[edge], page, interaction._latestPointer.eventTarget, element, rect, resizeOptions.margin || resize.defaultMargin);
      }
      resizeEdges.left = resizeEdges.left && !resizeEdges.right;
      resizeEdges.top = resizeEdges.top && !resizeEdges.bottom;
      if (resizeEdges.left || resizeEdges.right || resizeEdges.top || resizeEdges.bottom) {
        arg.action = {
          name: 'resize',
          edges: resizeEdges
        };
      }
    } else {
      var right = resizeOptions.axis !== 'y' && page.x > rect.right - resize.defaultMargin;
      var bottom = resizeOptions.axis !== 'x' && page.y > rect.bottom - resize.defaultMargin;
      if (right || bottom) {
        arg.action = {
          name: 'resize',
          axes: (right ? 'x' : '') + (bottom ? 'y' : '')
        };
      }
    }
    return arg.action ? false : undefined;
  }
  function resizable(interactable, options, scope) {
    if (is.object(options)) {
      interactable.options.resize.enabled = options.enabled !== false;
      interactable.setPerAction('resize', options);
      interactable.setOnEvents('resize', options);
      if (is.string(options.axis) && /^x$|^y$|^xy$/.test(options.axis)) {
        interactable.options.resize.axis = options.axis;
      } else if (options.axis === null) {
        interactable.options.resize.axis = scope.defaults.actions.resize.axis;
      }
      if (is.bool(options.preserveAspectRatio)) {
        interactable.options.resize.preserveAspectRatio = options.preserveAspectRatio;
      } else if (is.bool(options.square)) {
        interactable.options.resize.square = options.square;
      }
      return interactable;
    }
    if (is.bool(options)) {
      interactable.options.resize.enabled = options;
      return interactable;
    }
    return interactable.options.resize;
  }
  function checkResizeEdge(name, value, page, element, interactableElement, rect, margin) {
    // false, '', undefined, null
    if (!value) {
      return false;
    }

    // true value, use pointer coords and element rect
    if (value === true) {
      // if dimensions are negative, "switch" edges
      var width = is.number(rect.width) ? rect.width : rect.right - rect.left;
      var height = is.number(rect.height) ? rect.height : rect.bottom - rect.top;

      // don't use margin greater than half the relevent dimension
      margin = Math.min(margin, Math.abs((name === 'left' || name === 'right' ? width : height) / 2));
      if (width < 0) {
        if (name === 'left') {
          name = 'right';
        } else if (name === 'right') {
          name = 'left';
        }
      }
      if (height < 0) {
        if (name === 'top') {
          name = 'bottom';
        } else if (name === 'bottom') {
          name = 'top';
        }
      }
      if (name === 'left') {
        var edge = width >= 0 ? rect.left : rect.right;
        return page.x < edge + margin;
      }
      if (name === 'top') {
        var _edge = height >= 0 ? rect.top : rect.bottom;
        return page.y < _edge + margin;
      }
      if (name === 'right') {
        return page.x > (width >= 0 ? rect.right : rect.left) - margin;
      }
      if (name === 'bottom') {
        return page.y > (height >= 0 ? rect.bottom : rect.top) - margin;
      }
    }

    // the remaining checks require an element
    if (!is.element(element)) {
      return false;
    }
    return is.element(value) ?
    // the value is an element to use as a resize handle
    value === element :
    // otherwise check if element matches value as selector
    matchesUpTo(element, value, interactableElement);
  }

  /* eslint-disable multiline-ternary */
  // eslint-disable-next-line @typescript-eslint/consistent-type-imports
  function initCursors(browser) {
    return browser.isIe9 ? {
      x: 'e-resize',
      y: 's-resize',
      xy: 'se-resize',
      top: 'n-resize',
      left: 'w-resize',
      bottom: 's-resize',
      right: 'e-resize',
      topleft: 'se-resize',
      bottomright: 'se-resize',
      topright: 'ne-resize',
      bottomleft: 'ne-resize'
    } : {
      x: 'ew-resize',
      y: 'ns-resize',
      xy: 'nwse-resize',
      top: 'ns-resize',
      left: 'ew-resize',
      bottom: 'ns-resize',
      right: 'ew-resize',
      topleft: 'nwse-resize',
      bottomright: 'nwse-resize',
      topright: 'nesw-resize',
      bottomleft: 'nesw-resize'
    };
  }
  /* eslint-enable multiline-ternary */

  function start$7(_ref) {
    var iEvent = _ref.iEvent,
      interaction = _ref.interaction;
    if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) {
      return;
    }
    var resizeEvent = iEvent;
    var rect = interaction.rect;
    interaction._rects = {
      start: extend({}, rect),
      corrected: extend({}, rect),
      previous: extend({}, rect),
      delta: {
        left: 0,
        right: 0,
        width: 0,
        top: 0,
        bottom: 0,
        height: 0
      }
    };
    resizeEvent.edges = interaction.prepared.edges;
    resizeEvent.rect = interaction._rects.corrected;
    resizeEvent.deltaRect = interaction._rects.delta;
  }
  function move(_ref2) {
    var iEvent = _ref2.iEvent,
      interaction = _ref2.interaction;
    if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) return;
    var resizeEvent = iEvent;
    var resizeOptions = interaction.interactable.options.resize;
    var invert = resizeOptions.invert;
    var invertible = invert === 'reposition' || invert === 'negate';
    var current = interaction.rect;
    var _interaction$_rects = interaction._rects,
      startRect = _interaction$_rects.start,
      corrected = _interaction$_rects.corrected,
      deltaRect = _interaction$_rects.delta,
      previous = _interaction$_rects.previous;
    extend(previous, corrected);
    if (invertible) {
      // if invertible, copy the current rect
      extend(corrected, current);
      if (invert === 'reposition') {
        // swap edge values if necessary to keep width/height positive
        if (corrected.top > corrected.bottom) {
          var swap = corrected.top;
          corrected.top = corrected.bottom;
          corrected.bottom = swap;
        }
        if (corrected.left > corrected.right) {
          var _swap = corrected.left;
          corrected.left = corrected.right;
          corrected.right = _swap;
        }
      }
    } else {
      // if not invertible, restrict to minimum of 0x0 rect
      corrected.top = Math.min(current.top, startRect.bottom);
      corrected.bottom = Math.max(current.bottom, startRect.top);
      corrected.left = Math.min(current.left, startRect.right);
      corrected.right = Math.max(current.right, startRect.left);
    }
    corrected.width = corrected.right - corrected.left;
    corrected.height = corrected.bottom - corrected.top;
    for (var edge in corrected) {
      deltaRect[edge] = corrected[edge] - previous[edge];
    }
    resizeEvent.edges = interaction.prepared.edges;
    resizeEvent.rect = corrected;
    resizeEvent.deltaRect = deltaRect;
  }
  function end$1(_ref3) {
    var iEvent = _ref3.iEvent,
      interaction = _ref3.interaction;
    if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) return;
    var resizeEvent = iEvent;
    resizeEvent.edges = interaction.prepared.edges;
    resizeEvent.rect = interaction._rects.corrected;
    resizeEvent.deltaRect = interaction._rects.delta;
  }
  function updateEventAxes(_ref4) {
    var iEvent = _ref4.iEvent,
      interaction = _ref4.interaction;
    if (interaction.prepared.name !== 'resize' || !interaction.resizeAxes) return;
    var options = interaction.interactable.options;
    var resizeEvent = iEvent;
    if (options.resize.square) {
      if (interaction.resizeAxes === 'y') {
        resizeEvent.delta.x = resizeEvent.delta.y;
      } else {
        resizeEvent.delta.y = resizeEvent.delta.x;
      }
      resizeEvent.axes = 'xy';
    } else {
      resizeEvent.axes = interaction.resizeAxes;
      if (interaction.resizeAxes === 'x') {
        resizeEvent.delta.y = 0;
      } else if (interaction.resizeAxes === 'y') {
        resizeEvent.delta.x = 0;
      }
    }
  }
  var resize = {
    id: 'actions/resize',
    before: ['actions/drag'],
    install: install$d,
    listeners: {
      'interactions:new': function interactionsNew(_ref5) {
        var interaction = _ref5.interaction;
        interaction.resizeAxes = 'xy';
      },
      'interactions:action-start': function interactionsActionStart(arg) {
        start$7(arg);
        updateEventAxes(arg);
      },
      'interactions:action-move': function interactionsActionMove(arg) {
        move(arg);
        updateEventAxes(arg);
      },
      'interactions:action-end': end$1,
      'auto-start:check': resizeChecker
    },
    defaults: {
      square: false,
      preserveAspectRatio: false,
      axis: 'xy',
      // use default margin
      margin: NaN,
      // object with props left, right, top, bottom which are
      // true/false values to resize when the pointer is over that edge,
      // CSS selectors to match the handles for each direction
      // or the Elements for each handle
      edges: null,
      // a value of 'none' will limit the resize rect to a minimum of 0x0
      // 'negate' will alow the rect to have negative width/height
      // 'reposition' will keep the width/height positive by swapping
      // the top and bottom edges and/or swapping the left and right edges
      invert: 'none'
    },
    cursors: null,
    getCursor: function getCursor(_ref6) {
      var edges = _ref6.edges,
        axis = _ref6.axis,
        name = _ref6.name;
      var cursors = resize.cursors;
      var result = null;
      if (axis) {
        result = cursors[name + axis];
      } else if (edges) {
        var cursorKey = '';
        for (var _i2 = 0, _ref8 = ['top', 'bottom', 'left', 'right']; _i2 < _ref8.length; _i2++) {
          var edge = _ref8[_i2];
          if (edges[edge]) {
            cursorKey += edge;
          }
        }
        result = cursors[cursorKey];
      }
      return result;
    },
    filterEventType: function filterEventType(type) {
      return type.search('resize') === 0;
    },
    defaultMargin: null
  };
  var resize$1 = resize;

  /* eslint-disable import/no-duplicates -- for typescript module augmentations */
  /* eslint-enable import/no-duplicates */

  var actions = {
    id: 'actions',
    install: function install(scope) {
      scope.usePlugin(gesture$1);
      scope.usePlugin(resize$1);
      scope.usePlugin(drag$1);
      scope.usePlugin(drop$1);
    }
  };

  var lastTime = 0;
  var _request;
  var _cancel;
  function init(global) {
    _request = global.requestAnimationFrame;
    _cancel = global.cancelAnimationFrame;
    if (!_request) {
      var vendors = ['ms', 'moz', 'webkit', 'o'];
      for (var _i2 = 0; _i2 < vendors.length; _i2++) {
        var vendor = vendors[_i2];
        _request = global["".concat(vendor, "RequestAnimationFrame")];
        _cancel = global["".concat(vendor, "CancelAnimationFrame")] || global["".concat(vendor, "CancelRequestAnimationFrame")];
      }
    }
    _request = _request && _request.bind(global);
    _cancel = _cancel && _cancel.bind(global);
    if (!_request) {
      _request = function request(callback) {
        var currTime = Date.now();
        var timeToCall = Math.max(0, 16 - (currTime - lastTime));
        var token = global.setTimeout(function () {
          // eslint-disable-next-line n/no-callback-literal
          callback(currTime + timeToCall);
        }, timeToCall);
        lastTime = currTime + timeToCall;
        return token;
      };
      _cancel = function cancel(token) {
        return clearTimeout(token);
      };
    }
  }
  var raf = {
    request: function request(callback) {
      return _request(callback);
    },
    cancel: function cancel(token) {
      return _cancel(token);
    },
    init: init
  };

  function install$c(scope) {
    var defaults = scope.defaults,
      actions = scope.actions;
    scope.autoScroll = autoScroll;
    autoScroll.now = function () {
      return scope.now();
    };
    actions.phaselessTypes.autoscroll = true;
    defaults.perAction.autoScroll = autoScroll.defaults;
  }
  var autoScroll = {
    defaults: {
      enabled: false,
      margin: 60,
      // the item that is scrolled (Window or HTMLElement)
      container: null,
      // the scroll speed in pixels per second
      speed: 300
    },
    now: Date.now,
    interaction: null,
    i: 0,
    // the handle returned by window.setInterval

    // Direction each pulse is to scroll in
    x: 0,
    y: 0,
    isScrolling: false,
    prevTime: 0,
    margin: 0,
    speed: 0,
    start: function start(interaction) {
      autoScroll.isScrolling = true;
      raf.cancel(autoScroll.i);
      interaction.autoScroll = autoScroll;
      autoScroll.interaction = interaction;
      autoScroll.prevTime = autoScroll.now();
      autoScroll.i = raf.request(autoScroll.scroll);
    },
    stop: function stop() {
      autoScroll.isScrolling = false;
      if (autoScroll.interaction) {
        autoScroll.interaction.autoScroll = null;
      }
      raf.cancel(autoScroll.i);
    },
    // scroll the window by the values in scroll.x/y
    scroll: function scroll() {
      var interaction = autoScroll.interaction;
      var interactable = interaction.interactable,
        element = interaction.element;
      var actionName = interaction.prepared.name;
      var options = interactable.options[actionName].autoScroll;
      var container = getContainer(options.container, interactable, element);
      var now = autoScroll.now();
      // change in time in seconds
      var dt = (now - autoScroll.prevTime) / 1000;
      // displacement
      var s = options.speed * dt;
      if (s >= 1) {
        var scrollBy = {
          x: autoScroll.x * s,
          y: autoScroll.y * s
        };
        if (scrollBy.x || scrollBy.y) {
          var prevScroll = getScroll(container);
          if (is.window(container)) {
            container.scrollBy(scrollBy.x, scrollBy.y);
          } else if (container) {
            container.scrollLeft += scrollBy.x;
            container.scrollTop += scrollBy.y;
          }
          var curScroll = getScroll(container);
          var delta = {
            x: curScroll.x - prevScroll.x,
            y: curScroll.y - prevScroll.y
          };
          if (delta.x || delta.y) {
            interactable.fire({
              type: 'autoscroll',
              target: element,
              interactable: interactable,
              delta: delta,
              interaction: interaction,
              container: container
            });
          }
        }
        autoScroll.prevTime = now;
      }
      if (autoScroll.isScrolling) {
        raf.cancel(autoScroll.i);
        autoScroll.i = raf.request(autoScroll.scroll);
      }
    },
    check: function check(interactable, actionName) {
      var _options$actionName$a;
      var options = interactable.options;
      return (_options$actionName$a = options[actionName].autoScroll) == null ? void 0 : _options$actionName$a.enabled;
    },
    onInteractionMove: function onInteractionMove(_ref) {
      var interaction = _ref.interaction,
        pointer = _ref.pointer;
      if (!(interaction.interacting() && autoScroll.check(interaction.interactable, interaction.prepared.name))) {
        return;
      }
      if (interaction.simulation) {
        autoScroll.x = autoScroll.y = 0;
        return;
      }
      var top;
      var right;
      var bottom;
      var left;
      var interactable = interaction.interactable,
        element = interaction.element;
      var actionName = interaction.prepared.name;
      var options = interactable.options[actionName].autoScroll;
      var container = getContainer(options.container, interactable, element);
      if (is.window(container)) {
        left = pointer.clientX < autoScroll.margin;
        top = pointer.clientY < autoScroll.margin;
        right = pointer.clientX > container.innerWidth - autoScroll.margin;
        bottom = pointer.clientY > container.innerHeight - autoScroll.margin;
      } else {
        var rect = getElementClientRect(container);
        left = pointer.clientX < rect.left + autoScroll.margin;
        top = pointer.clientY < rect.top + autoScroll.margin;
        right = pointer.clientX > rect.right - autoScroll.margin;
        bottom = pointer.clientY > rect.bottom - autoScroll.margin;
      }
      autoScroll.x = right ? 1 : left ? -1 : 0;
      autoScroll.y = bottom ? 1 : top ? -1 : 0;
      if (!autoScroll.isScrolling) {
        // set the autoScroll properties to those of the target
        autoScroll.margin = options.margin;
        autoScroll.speed = options.speed;
        autoScroll.start(interaction);
      }
    }
  };
  function getContainer(value, interactable, element) {
    return (is.string(value) ? getStringOptionResult(value, interactable, element) : value) || getWindow(element);
  }
  function getScroll(container) {
    if (is.window(container)) {
      container = window.document.body;
    }
    return {
      x: container.scrollLeft,
      y: container.scrollTop
    };
  }
  var autoScrollPlugin = {
    id: 'auto-scroll',
    install: install$c,
    listeners: {
      'interactions:new': function interactionsNew(_ref3) {
        var interaction = _ref3.interaction;
        interaction.autoScroll = null;
      },
      'interactions:destroy': function interactionsDestroy(_ref4) {
        var interaction = _ref4.interaction;
        interaction.autoScroll = null;
        autoScroll.stop();
        if (autoScroll.interaction) {
          autoScroll.interaction = null;
        }
      },
      'interactions:stop': autoScroll.stop,
      'interactions:action-move': function interactionsActionMove(arg) {
        return autoScroll.onInteractionMove(arg);
      }
    }
  };
  var autoScroll$1 = autoScrollPlugin;

  function warnOnce(method, message) {
    var warned = false;
    return function () {
      if (!warned) {
        win.console.warn(message);
        warned = true;
      }
      return method.apply(this, arguments);
    };
  }
  function copyAction(dest, src) {
    dest.name = src.name;
    dest.axis = src.axis;
    dest.edges = src.edges;
    return dest;
  }

  function install$b(scope) {
    var Interactable = scope.Interactable;
    Interactable.prototype.getAction = function getAction(pointer, event, interaction, element) {
      var action = defaultActionChecker(this, event, interaction, element, scope);
      if (this.options.actionChecker) {
        return this.options.actionChecker(pointer, event, action, this, element, interaction);
      }
      return action;
    };
    Interactable.prototype.ignoreFrom = warnOnce(function (newValue) {
      return this._backCompatOption('ignoreFrom', newValue);
    }, 'Interactable.ignoreFrom() has been deprecated. Use Interactble.draggable({ignoreFrom: newValue}).');
    Interactable.prototype.allowFrom = warnOnce(function (newValue) {
      return this._backCompatOption('allowFrom', newValue);
    }, 'Interactable.allowFrom() has been deprecated. Use Interactble.draggable({allowFrom: newValue}).');
    Interactable.prototype.actionChecker = actionChecker;
    Interactable.prototype.styleCursor = styleCursor;
  }
  function defaultActionChecker(interactable, event, interaction, element, scope) {
    var rect = interactable.getRect(element);
    var buttons = event.buttons || {
      0: 1,
      1: 4,
      3: 8,
      4: 16
    }[event.button];
    var arg = {
      action: null,
      interactable: interactable,
      interaction: interaction,
      element: element,
      rect: rect,
      buttons: buttons
    };
    scope.fire('auto-start:check', arg);
    return arg.action;
  }
  function styleCursor(newValue) {
    if (is.bool(newValue)) {
      this.options.styleCursor = newValue;
      return this;
    }
    if (newValue === null) {
      delete this.options.styleCursor;
      return this;
    }
    return this.options.styleCursor;
  }
  function actionChecker(checker) {
    if (is.func(checker)) {
      this.options.actionChecker = checker;
      return this;
    }
    if (checker === null) {
      delete this.options.actionChecker;
      return this;
    }
    return this.options.actionChecker;
  }
  var InteractableMethods = {
    id: 'auto-start/interactableMethods',
    install: install$b
  };

  /* eslint-enable import/no-duplicates */

  function install$a(scope) {
    var interact = scope.interactStatic,
      defaults = scope.defaults;
    scope.usePlugin(InteractableMethods);
    defaults.base.actionChecker = null;
    defaults.base.styleCursor = true;
    extend(defaults.perAction, {
      manualStart: false,
      max: Infinity,
      maxPerElement: 1,
      allowFrom: null,
      ignoreFrom: null,
      // only allow left button by default
      // see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons#Return_value
      mouseButtons: 1
    });
    interact.maxInteractions = function (newValue) {
      return maxInteractions(newValue, scope);
    };
    scope.autoStart = {
      // Allow this many interactions to happen simultaneously
      maxInteractions: Infinity,
      withinInteractionLimit: withinInteractionLimit,
      cursorElement: null
    };
  }
  function prepareOnDown(_ref, scope) {
    var interaction = _ref.interaction,
      pointer = _ref.pointer,
      event = _ref.event,
      eventTarget = _ref.eventTarget;
    if (interaction.interacting()) return;
    var actionInfo = getActionInfo(interaction, pointer, event, eventTarget, scope);
    prepare(interaction, actionInfo, scope);
  }
  function prepareOnMove(_ref2, scope) {
    var interaction = _ref2.interaction,
      pointer = _ref2.pointer,
      event = _ref2.event,
      eventTarget = _ref2.eventTarget;
    if (interaction.pointerType !== 'mouse' || interaction.pointerIsDown || interaction.interacting()) return;
    var actionInfo = getActionInfo(interaction, pointer, event, eventTarget, scope);
    prepare(interaction, actionInfo, scope);
  }
  function startOnMove(arg, scope) {
    var interaction = arg.interaction;
    if (!interaction.pointerIsDown || interaction.interacting() || !interaction.pointerWasMoved || !interaction.prepared.name) {
      return;
    }
    scope.fire('autoStart:before-start', arg);
    var interactable = interaction.interactable;
    var actionName = interaction.prepared.name;
    if (actionName && interactable) {
      // check manualStart and interaction limit
      if (interactable.options[actionName].manualStart || !withinInteractionLimit(interactable, interaction.element, interaction.prepared, scope)) {
        interaction.stop();
      } else {
        interaction.start(interaction.prepared, interactable, interaction.element);
        setInteractionCursor(interaction, scope);
      }
    }
  }
  function clearCursorOnStop(_ref3, scope) {
    var interaction = _ref3.interaction;
    var interactable = interaction.interactable;
    if (interactable && interactable.options.styleCursor) {
      setCursor(interaction.element, '', scope);
    }
  }

  // Check if the current interactable supports the action.
  // If so, return the validated action. Otherwise, return null
  function validateAction(action, interactable, element, eventTarget, scope) {
    if (interactable.testIgnoreAllow(interactable.options[action.name], element, eventTarget) && interactable.options[action.name].enabled && withinInteractionLimit(interactable, element, action, scope)) {
      return action;
    }
    return null;
  }
  function validateMatches(interaction, pointer, event, matches, matchElements, eventTarget, scope) {
    for (var i = 0, len = matches.length; i < len; i++) {
      var match = matches[i];
      var matchElement = matchElements[i];
      var matchAction = match.getAction(pointer, event, interaction, matchElement);
      if (!matchAction) {
        continue;
      }
      var action = validateAction(matchAction, match, matchElement, eventTarget, scope);
      if (action) {
        return {
          action: action,
          interactable: match,
          element: matchElement
        };
      }
    }
    return {
      action: null,
      interactable: null,
      element: null
    };
  }
  function getActionInfo(interaction, pointer, event, eventTarget, scope) {
    var matches = [];
    var matchElements = [];
    var element = eventTarget;
    function pushMatches(interactable) {
      matches.push(interactable);
      matchElements.push(element);
    }
    while (is.element(element)) {
      matches = [];
      matchElements = [];
      scope.interactables.forEachMatch(element, pushMatches);
      var actionInfo = validateMatches(interaction, pointer, event, matches, matchElements, eventTarget, scope);
      if (actionInfo.action && !actionInfo.interactable.options[actionInfo.action.name].manualStart) {
        return actionInfo;
      }
      element = parentNode(element);
    }
    return {
      action: null,
      interactable: null,
      element: null
    };
  }
  function prepare(interaction, _ref4, scope) {
    var action = _ref4.action,
      interactable = _ref4.interactable,
      element = _ref4.element;
    action = action || {
      name: null
    };
    interaction.interactable = interactable;
    interaction.element = element;
    copyAction(interaction.prepared, action);
    interaction.rect = interactable && action.name ? interactable.getRect(element) : null;
    setInteractionCursor(interaction, scope);
    scope.fire('autoStart:prepared', {
      interaction: interaction
    });
  }
  function withinInteractionLimit(interactable, element, action, scope) {
    var options = interactable.options;
    var maxActions = options[action.name].max;
    var maxPerElement = options[action.name].maxPerElement;
    var autoStartMax = scope.autoStart.maxInteractions;
    var activeInteractions = 0;
    var interactableCount = 0;
    var elementCount = 0;

    // no actions if any of these values == 0
    if (!(maxActions && maxPerElement && autoStartMax)) {
      return false;
    }
    for (var _i2 = 0, _scope$interactions$l2 = scope.interactions.list; _i2 < _scope$interactions$l2.length; _i2++) {
      var interaction = _scope$interactions$l2[_i2];
      var otherAction = interaction.prepared.name;
      if (!interaction.interacting()) {
        continue;
      }
      activeInteractions++;
      if (activeInteractions >= autoStartMax) {
        return false;
      }
      if (interaction.interactable !== interactable) {
        continue;
      }
      interactableCount += otherAction === action.name ? 1 : 0;
      if (interactableCount >= maxActions) {
        return false;
      }
      if (interaction.element === element) {
        elementCount++;
        if (otherAction === action.name && elementCount >= maxPerElement) {
          return false;
        }
      }
    }
    return autoStartMax > 0;
  }
  function maxInteractions(newValue, scope) {
    if (is.number(newValue)) {
      scope.autoStart.maxInteractions = newValue;
      return this;
    }
    return scope.autoStart.maxInteractions;
  }
  function setCursor(element, cursor, scope) {
    var prevCursorElement = scope.autoStart.cursorElement;
    if (prevCursorElement && prevCursorElement !== element) {
      prevCursorElement.style.cursor = '';
    }
    element.ownerDocument.documentElement.style.cursor = cursor;
    element.style.cursor = cursor;
    scope.autoStart.cursorElement = cursor ? element : null;
  }
  function setInteractionCursor(interaction, scope) {
    var interactable = interaction.interactable,
      element = interaction.element,
      prepared = interaction.prepared;
    if (!(interaction.pointerType === 'mouse' && interactable && interactable.options.styleCursor)) {
      // clear previous target element cursor
      if (scope.autoStart.cursorElement) {
        setCursor(scope.autoStart.cursorElement, '', scope);
      }
      return;
    }
    var cursor = '';
    if (prepared.name) {
      var cursorChecker = interactable.options[prepared.name].cursorChecker;
      if (is.func(cursorChecker)) {
        cursor = cursorChecker(prepared, interactable, element, interaction._interacting);
      } else {
        cursor = scope.actions.map[prepared.name].getCursor(prepared);
      }
    }
    setCursor(interaction.element, cursor || '', scope);
  }
  var autoStart$1 = {
    id: 'auto-start/base',
    before: ['actions'],
    install: install$a,
    listeners: {
      'interactions:down': prepareOnDown,
      'interactions:move': function interactionsMove(arg, scope) {
        prepareOnMove(arg, scope);
        startOnMove(arg, scope);
      },
      'interactions:stop': clearCursorOnStop
    },
    maxInteractions: maxInteractions,
    withinInteractionLimit: withinInteractionLimit,
    validateAction: validateAction
  };
  var autoStart$2 = autoStart$1;

  function beforeStart(_ref, scope) {
    var interaction = _ref.interaction,
      eventTarget = _ref.eventTarget,
      dx = _ref.dx,
      dy = _ref.dy;
    if (interaction.prepared.name !== 'drag') return;

    // check if a drag is in the correct axis
    var absX = Math.abs(dx);
    var absY = Math.abs(dy);
    var targetOptions = interaction.interactable.options.drag;
    var startAxis = targetOptions.startAxis;
    var currentAxis = absX > absY ? 'x' : absX < absY ? 'y' : 'xy';
    interaction.prepared.axis = targetOptions.lockAxis === 'start' ? currentAxis[0] // always lock to one axis even if currentAxis === 'xy'
    : targetOptions.lockAxis;

    // if the movement isn't in the startAxis of the interactable
    if (currentAxis !== 'xy' && startAxis !== 'xy' && startAxis !== currentAxis) {
      interaction.prepared.name = null;

      // then try to get a drag from another ineractable
      var element = eventTarget;
      var getDraggable = function getDraggable(interactable) {
        if (interactable === interaction.interactable) return;
        var options = interaction.interactable.options.drag;
        if (!options.manualStart && interactable.testIgnoreAllow(options, element, eventTarget)) {
          var action = interactable.getAction(interaction.downPointer, interaction.downEvent, interaction, element);
          if (action && action.name === 'drag' && checkStartAxis(currentAxis, interactable) && autoStart$2.validateAction(action, interactable, element, eventTarget, scope)) {
            return interactable;
          }
        }
      };

      // check all interactables
      while (is.element(element)) {
        var interactable = scope.interactables.forEachMatch(element, getDraggable);
        if (interactable) {
          interaction.prepared.name = 'drag';
          interaction.interactable = interactable;
          interaction.element = element;
          break;
        }
        element = parentNode(element);
      }
    }
  }
  function checkStartAxis(startAxis, interactable) {
    if (!interactable) {
      return false;
    }
    var thisAxis = interactable.options.drag.startAxis;
    return startAxis === 'xy' || thisAxis === 'xy' || thisAxis === startAxis;
  }
  var dragAxis = {
    id: 'auto-start/dragAxis',
    listeners: {
      'autoStart:before-start': beforeStart
    }
  };

  /* eslint-disable import/no-duplicates -- for typescript module augmentations */
  /* eslint-enable */

  function install$9(scope) {
    var defaults = scope.defaults;
    scope.usePlugin(autoStart$2);
    defaults.perAction.hold = 0;
    defaults.perAction.delay = 0;
  }
  function getHoldDuration(interaction) {
    var actionName = interaction.prepared && interaction.prepared.name;
    if (!actionName) {
      return null;
    }
    var options = interaction.interactable.options;
    return options[actionName].hold || options[actionName].delay;
  }
  var hold = {
    id: 'auto-start/hold',
    install: install$9,
    listeners: {
      'interactions:new': function interactionsNew(_ref) {
        var interaction = _ref.interaction;
        interaction.autoStartHoldTimer = null;
      },
      'autoStart:prepared': function autoStartPrepared(_ref2) {
        var interaction = _ref2.interaction;
        var hold = getHoldDuration(interaction);
        if (hold > 0) {
          interaction.autoStartHoldTimer = setTimeout(function () {
            interaction.start(interaction.prepared, interaction.interactable, interaction.element);
          }, hold);
        }
      },
      'interactions:move': function interactionsMove(_ref3) {
        var interaction = _ref3.interaction,
          duplicate = _ref3.duplicate;
        if (interaction.autoStartHoldTimer && interaction.pointerWasMoved && !duplicate) {
          clearTimeout(interaction.autoStartHoldTimer);
          interaction.autoStartHoldTimer = null;
        }
      },
      // prevent regular down->move autoStart
      'autoStart:before-start': function autoStartBeforeStart(_ref4) {
        var interaction = _ref4.interaction;
        var holdDuration = getHoldDuration(interaction);
        if (holdDuration > 0) {
          interaction.prepared.name = null;
        }
      }
    },
    getHoldDuration: getHoldDuration
  };
  var hold$1 = hold;

  /* eslint-disable import/no-duplicates -- for typescript module augmentations */
  /* eslint-enable import/no-duplicates */

  var autoStart = {
    id: 'auto-start',
    install: function install(scope) {
      scope.usePlugin(autoStart$2);
      scope.usePlugin(hold$1);
      scope.usePlugin(dragAxis);
    }
  };

  var preventDefault = function preventDefault(newValue) {
    if (/^(always|never|auto)$/.test(newValue)) {
      this.options.preventDefault = newValue;
      return this;
    }
    if (is.bool(newValue)) {
      this.options.preventDefault = newValue ? 'always' : 'never';
      return this;
    }
    return this.options.preventDefault;
  };
  function checkAndPreventDefault(interactable, scope, event) {
    var setting = interactable.options.preventDefault;
    if (setting === 'never') return;
    if (setting === 'always') {
      event.preventDefault();
      return;
    }

    // setting === 'auto'

    // if the browser supports passive event listeners and isn't running on iOS,
    // don't preventDefault of touch{start,move} events. CSS touch-action and
    // user-select should be used instead of calling event.preventDefault().
    if (scope.events.supportsPassive && /^touch(start|move)$/.test(event.type)) {
      var doc = getWindow(event.target).document;
      var docOptions = scope.getDocOptions(doc);
      if (!(docOptions && docOptions.events) || docOptions.events.passive !== false) {
        return;
      }
    }

    // don't preventDefault of pointerdown events
    if (/^(mouse|pointer|touch)*(down|start)/i.test(event.type)) {
      return;
    }

    // don't preventDefault on editable elements
    if (is.element(event.target) && matchesSelector(event.target, 'input,select,textarea,[contenteditable=true],[contenteditable=true] *')) {
      return;
    }
    event.preventDefault();
  }
  function onInteractionEvent(_ref) {
    var interaction = _ref.interaction,
      event = _ref.event;
    if (interaction.interactable) {
      interaction.interactable.checkAndPreventDefault(event);
    }
  }
  function install$8(scope) {
    var Interactable = scope.Interactable;
    Interactable.prototype.preventDefault = preventDefault;
    Interactable.prototype.checkAndPreventDefault = function (event) {
      return checkAndPreventDefault(this, scope, event);
    };

    // prevent native HTML5 drag on interact.js target elements
    scope.interactions.docEvents.push({
      type: 'dragstart',
      listener: function listener(event) {
        for (var _i2 = 0, _scope$interactions$l2 = scope.interactions.list; _i2 < _scope$interactions$l2.length; _i2++) {
          var interaction = _scope$interactions$l2[_i2];
          if (interaction.element && (interaction.element === event.target || nodeContains(interaction.element, event.target))) {
            interaction.interactable.checkAndPreventDefault(event);
            return;
          }
        }
      }
    });
  }
  var interactablePreventDefault = {
    id: 'core/interactablePreventDefault',
    install: install$8,
    listeners: ['down', 'move', 'up', 'cancel'].reduce(function (acc, eventType) {
      acc["interactions:".concat(eventType)] = onInteractionEvent;
      return acc;
    }, {})
  };

  function isNonNativeEvent(type, actions) {
    if (actions.phaselessTypes[type]) {
      return true;
    }
    for (var name in actions.map) {
      if (type.indexOf(name) === 0 && type.substr(name.length) in actions.phases) {
        return true;
      }
    }
    return false;
  }

  var CheckName = /*#__PURE__*/function (CheckName) {
    CheckName["touchAction"] = "touchAction";
    CheckName["boxSizing"] = "boxSizing";
    CheckName["noListeners"] = "noListeners";
    return CheckName;
  }(CheckName || {});
  var prefix = '[interact.js] ';
  var links = {
    touchAction: 'https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action',
    boxSizing: 'https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing'
  };

  // eslint-disable-next-line no-undef
  var isProduction = "development" === 'production';
  function install$7(scope) {
    var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
      logger = _ref.logger;
    var Interactable = scope.Interactable,
      defaults = scope.defaults;
    scope.logger = logger || console;
    defaults.base.devTools = {
      ignore: {}
    };
    Interactable.prototype.devTools = function (options) {
      if (options) {
        extend(this.options.devTools, options);
        return this;
      }
      return this.options.devTools;
    };

    // can't set native events on non string targets without `addEventListener` prop
    var _onOff = Interactable.prototype._onOff;
    Interactable.prototype._onOff = function (method, typeArg, listenerArg, options, filter) {
      if (is.string(this.target) || this.target.addEventListener) {
        return _onOff.call(this, method, typeArg, listenerArg, options, filter);
      }
      if (is.object(typeArg) && !is.array(typeArg)) {
        options = listenerArg;
        listenerArg = null;
      }
      var normalizedListeners = normalize(typeArg, listenerArg, filter);
      for (var type in normalizedListeners) {
        if (isNonNativeEvent(type, scope.actions)) continue;
        scope.logger.warn(prefix + "Can't add native \"".concat(type, "\" event listener to target without `addEventListener(type, listener, options)` prop."));
      }
      return _onOff.call(this, method, normalizedListeners, options);
    };
  }
  var checks = [{
    name: CheckName.touchAction,
    perform: function perform(_ref2) {
      var element = _ref2.element;
      return !!element && !parentHasStyle(element, 'touchAction', /pan-|pinch|none/);
    },
    getInfo: function getInfo(_ref3) {
      var element = _ref3.element;
      return [element, links.touchAction];
    },
    text: 'Consider adding CSS "touch-action: none" to this element\n'
  }, {
    name: CheckName.boxSizing,
    perform: function perform(interaction) {
      var element = interaction.element;
      return interaction.prepared.name === 'resize' && element instanceof domObjects$1.HTMLElement && !hasStyle(element, 'boxSizing', /border-box/);
    },
    text: 'Consider adding CSS "box-sizing: border-box" to this resizable element',
    getInfo: function getInfo(_ref4) {
      var element = _ref4.element;
      return [element, links.boxSizing];
    }
  }, {
    name: CheckName.noListeners,
    perform: function perform(interaction) {
      var _interaction$interact;
      var actionName = interaction.prepared.name;
      var moveListeners = ((_interaction$interact = interaction.interactable) == null ? void 0 : _interaction$interact.events.types["".concat(actionName, "move")]) || [];
      return !moveListeners.length;
    },
    getInfo: function getInfo(interaction) {
      return [interaction.prepared.name, interaction.interactable];
    },
    text: 'There are no listeners set for this action'
  }];
  function hasStyle(element, prop, styleRe) {
    var value = element.style[prop] || win.getComputedStyle(element)[prop];
    return styleRe.test((value || '').toString());
  }
  function parentHasStyle(element, prop, styleRe) {
    var parent = element;
    while (is.element(parent)) {
      if (hasStyle(parent, prop, styleRe)) {
        return true;
      }
      parent = parentNode(parent);
    }
    return false;
  }
  var id = 'dev-tools';
  var defaultExport = isProduction ? {
    id: id,
    install: function install() {}
  } : {
    id: id,
    install: install$7,
    listeners: {
      'interactions:action-start': function interactionsActionStart(_ref5, scope) {
        var interaction = _ref5.interaction;
        for (var _i2 = 0; _i2 < checks.length; _i2++) {
          var check = checks[_i2];
          var options = interaction.interactable && interaction.interactable.options;
          if (!(options && options.devTools && options.devTools.ignore[check.name]) && check.perform(interaction)) {
            var _scope$logger;
            (_scope$logger = scope.logger).warn.apply(_scope$logger, [prefix + check.text].concat(check.getInfo(interaction)));
          }
        }
      }
    },
    checks: checks,
    CheckName: CheckName,
    links: links,
    prefix: prefix
  };
  var devTools = defaultExport;

  // tslint:disable-next-line ban-types
  function clone(source) {
    var dest = {};
    for (var prop in source) {
      var value = source[prop];
      if (is.plainObject(value)) {
        dest[prop] = clone(value);
      } else if (is.array(value)) {
        dest[prop] = from(value);
      } else {
        dest[prop] = value;
      }
    }
    return dest;
  }

  var Modification = /*#__PURE__*/function () {
    function Modification(interaction) {
      _classCallCheck(this, Modification);
      this.states = [];
      this.startOffset = {
        left: 0,
        right: 0,
        top: 0,
        bottom: 0
      };
      this.startDelta = void 0;
      this.result = void 0;
      this.endResult = void 0;
      this.startEdges = void 0;
      this.edges = void 0;
      this.interaction = void 0;
      this.interaction = interaction;
      this.result = createResult();
      this.edges = {
        left: false,
        right: false,
        top: false,
        bottom: false
      };
    }
    _createClass(Modification, [{
      key: "start",
      value: function start(_ref, pageCoords) {
        var phase = _ref.phase;
        var interaction = this.interaction;
        var modifierList = getModifierList(interaction);
        this.prepareStates(modifierList);
        this.startEdges = extend({}, interaction.edges);
        this.edges = extend({}, this.startEdges);
        this.startOffset = getRectOffset(interaction.rect, pageCoords);
        this.startDelta = {
          x: 0,
          y: 0
        };
        var arg = this.fillArg({
          phase: phase,
          pageCoords: pageCoords,
          preEnd: false
        });
        this.result = createResult();
        this.startAll(arg);
        var result = this.result = this.setAll(arg);
        return result;
      }
    }, {
      key: "fillArg",
      value: function fillArg(arg) {
        var interaction = this.interaction;
        arg.interaction = interaction;
        arg.interactable = interaction.interactable;
        arg.element = interaction.element;
        arg.rect || (arg.rect = interaction.rect);
        arg.edges || (arg.edges = this.startEdges);
        arg.startOffset = this.startOffset;
        return arg;
      }
    }, {
      key: "startAll",
      value: function startAll(arg) {
        for (var _i2 = 0, _this$states2 = this.states; _i2 < _this$states2.length; _i2++) {
          var state = _this$states2[_i2];
          if (state.methods.start) {
            arg.state = state;
            state.methods.start(arg);
          }
        }
      }
    }, {
      key: "setAll",
      value: function setAll(arg) {
        var phase = arg.phase,
          preEnd = arg.preEnd,
          skipModifiers = arg.skipModifiers,
          unmodifiedRect = arg.rect,
          unmodifiedEdges = arg.edges;
        arg.coords = extend({}, arg.pageCoords);
        arg.rect = extend({}, unmodifiedRect);
        arg.edges = extend({}, unmodifiedEdges);
        var states = skipModifiers ? this.states.slice(skipModifiers) : this.states;
        var newResult = createResult(arg.coords, arg.rect);
        for (var _i4 = 0; _i4 < states.length; _i4++) {
          var _state$methods;
          var state = states[_i4];
          var options = state.options;
          var lastModifierCoords = extend({}, arg.coords);
          var returnValue = null;
          if ((_state$methods = state.methods) != null && _state$methods.set && this.shouldDo(options, preEnd, phase)) {
            arg.state = state;
            returnValue = state.methods.set(arg);
            addEdges(arg.edges, arg.rect, {
              x: arg.coords.x - lastModifierCoords.x,
              y: arg.coords.y - lastModifierCoords.y
            });
          }
          newResult.eventProps.push(returnValue);
        }
        extend(this.edges, arg.edges);
        newResult.delta.x = arg.coords.x - arg.pageCoords.x;
        newResult.delta.y = arg.coords.y - arg.pageCoords.y;
        newResult.rectDelta.left = arg.rect.left - unmodifiedRect.left;
        newResult.rectDelta.right = arg.rect.right - unmodifiedRect.right;
        newResult.rectDelta.top = arg.rect.top - unmodifiedRect.top;
        newResult.rectDelta.bottom = arg.rect.bottom - unmodifiedRect.bottom;
        var prevCoords = this.result.coords;
        var prevRect = this.result.rect;
        if (prevCoords && prevRect) {
          var rectChanged = newResult.rect.left !== prevRect.left || newResult.rect.right !== prevRect.right || newResult.rect.top !== prevRect.top || newResult.rect.bottom !== prevRect.bottom;
          newResult.changed = rectChanged || prevCoords.x !== newResult.coords.x || prevCoords.y !== newResult.coords.y;
        }
        return newResult;
      }
    }, {
      key: "applyToInteraction",
      value: function applyToInteraction(arg) {
        var interaction = this.interaction;
        var phase = arg.phase;
        var curCoords = interaction.coords.cur;
        var startCoords = interaction.coords.start;
        var result = this.result,
          startDelta = this.startDelta;
        var curDelta = result.delta;
        if (phase === 'start') {
          extend(this.startDelta, result.delta);
        }
        for (var _i6 = 0, _ref3 = [[startCoords, startDelta], [curCoords, curDelta]]; _i6 < _ref3.length; _i6++) {
          var _ref3$_i = _ref3[_i6],
            coordsSet = _ref3$_i[0],
            delta = _ref3$_i[1];
          coordsSet.page.x += delta.x;
          coordsSet.page.y += delta.y;
          coordsSet.client.x += delta.x;
          coordsSet.client.y += delta.y;
        }
        var rectDelta = this.result.rectDelta;
        var rect = arg.rect || interaction.rect;
        rect.left += rectDelta.left;
        rect.right += rectDelta.right;
        rect.top += rectDelta.top;
        rect.bottom += rectDelta.bottom;
        rect.width = rect.right - rect.left;
        rect.height = rect.bottom - rect.top;
      }
    }, {
      key: "setAndApply",
      value: function setAndApply(arg) {
        var interaction = this.interaction;
        var phase = arg.phase,
          preEnd = arg.preEnd,
          skipModifiers = arg.skipModifiers;
        var result = this.setAll(this.fillArg({
          preEnd: preEnd,
          phase: phase,
          pageCoords: arg.modifiedCoords || interaction.coords.cur.page
        }));
        this.result = result;

        // don't fire an action move if a modifier would keep the event in the same
        // cordinates as before
        if (!result.changed && (!skipModifiers || skipModifiers < this.states.length) && interaction.interacting()) {
          return false;
        }
        if (arg.modifiedCoords) {
          var page = interaction.coords.cur.page;
          var adjustment = {
            x: arg.modifiedCoords.x - page.x,
            y: arg.modifiedCoords.y - page.y
          };
          result.coords.x += adjustment.x;
          result.coords.y += adjustment.y;
          result.delta.x += adjustment.x;
          result.delta.y += adjustment.y;
        }
        this.applyToInteraction(arg);
      }
    }, {
      key: "beforeEnd",
      value: function beforeEnd(arg) {
        var interaction = arg.interaction,
          event = arg.event;
        var states = this.states;
        if (!states || !states.length) {
          return;
        }
        var doPreend = false;
        for (var _i8 = 0; _i8 < states.length; _i8++) {
          var state = states[_i8];
          arg.state = state;
          var options = state.options,
            methods = state.methods;
          var endPosition = methods.beforeEnd && methods.beforeEnd(arg);
          if (endPosition) {
            this.endResult = endPosition;
            return false;
          }
          doPreend = doPreend || !doPreend && this.shouldDo(options, true, arg.phase, true);
        }
        if (doPreend) {
          // trigger a final modified move before ending
          interaction.move({
            event: event,
            preEnd: true
          });
        }
      }
    }, {
      key: "stop",
      value: function stop(arg) {
        var interaction = arg.interaction;
        if (!this.states || !this.states.length) {
          return;
        }
        var modifierArg = extend({
          states: this.states,
          interactable: interaction.interactable,
          element: interaction.element,
          rect: null
        }, arg);
        this.fillArg(modifierArg);
        for (var _i10 = 0, _this$states4 = this.states; _i10 < _this$states4.length; _i10++) {
          var state = _this$states4[_i10];
          modifierArg.state = state;
          if (state.methods.stop) {
            state.methods.stop(modifierArg);
          }
        }
        this.states = null;
        this.endResult = null;
      }
    }, {
      key: "prepareStates",
      value: function prepareStates(modifierList) {
        this.states = [];
        for (var index = 0; index < modifierList.length; index++) {
          var _modifierList$index = modifierList[index],
            options = _modifierList$index.options,
            methods = _modifierList$index.methods,
            name = _modifierList$index.name;
          this.states.push({
            options: options,
            methods: methods,
            index: index,
            name: name
          });
        }
        return this.states;
      }
    }, {
      key: "restoreInteractionCoords",
      value: function restoreInteractionCoords(_ref4) {
        var _ref4$interaction = _ref4.interaction,
          coords = _ref4$interaction.coords,
          rect = _ref4$interaction.rect,
          modification = _ref4$interaction.modification;
        if (!modification.result) return;
        var startDelta = modification.startDelta;
        var _modification$result = modification.result,
          curDelta = _modification$result.delta,
          rectDelta = _modification$result.rectDelta;
        var coordsAndDeltas = [[coords.start, startDelta], [coords.cur, curDelta]];
        for (var _i12 = 0, _ref6 = coordsAndDeltas; _i12 < _ref6.length; _i12++) {
          var _ref6$_i = _ref6[_i12],
            coordsSet = _ref6$_i[0],
            delta = _ref6$_i[1];
          coordsSet.page.x -= delta.x;
          coordsSet.page.y -= delta.y;
          coordsSet.client.x -= delta.x;
          coordsSet.client.y -= delta.y;
        }
        rect.left -= rectDelta.left;
        rect.right -= rectDelta.right;
        rect.top -= rectDelta.top;
        rect.bottom -= rectDelta.bottom;
      }
    }, {
      key: "shouldDo",
      value: function shouldDo(options, preEnd, phase, requireEndOnly) {
        if (
        // ignore disabled modifiers
        !options || options.enabled === false ||
        // check if we require endOnly option to fire move before end
        requireEndOnly && !options.endOnly ||
        // don't apply endOnly modifiers when not ending
        options.endOnly && !preEnd ||
        // check if modifier should run be applied on start
        phase === 'start' && !options.setStart) {
          return false;
        }
        return true;
      }
    }, {
      key: "copyFrom",
      value: function copyFrom(other) {
        this.startOffset = other.startOffset;
        this.startDelta = other.startDelta;
        this.startEdges = other.startEdges;
        this.edges = other.edges;
        this.states = other.states.map(function (s) {
          return clone(s);
        });
        this.result = createResult(extend({}, other.result.coords), extend({}, other.result.rect));
      }
    }, {
      key: "destroy",
      value: function destroy() {
        for (var prop in this) {
          this[prop] = null;
        }
      }
    }]);
    return Modification;
  }();
  function createResult(coords, rect) {
    return {
      rect: rect,
      coords: coords,
      delta: {
        x: 0,
        y: 0
      },
      rectDelta: {
        left: 0,
        right: 0,
        top: 0,
        bottom: 0
      },
      eventProps: [],
      changed: true
    };
  }
  function getModifierList(interaction) {
    var actionOptions = interaction.interactable.options[interaction.prepared.name];
    var actionModifiers = actionOptions.modifiers;
    if (actionModifiers && actionModifiers.length) {
      return actionModifiers;
    }
    return ['snap', 'snapSize', 'snapEdges', 'restrict', 'restrictEdges', 'restrictSize'].map(function (type) {
      var options = actionOptions[type];
      return options && options.enabled && {
        options: options,
        methods: options._methods
      };
    }).filter(function (m) {
      return !!m;
    });
  }
  function getRectOffset(rect, coords) {
    return rect ? {
      left: coords.x - rect.left,
      top: coords.y - rect.top,
      right: rect.right - coords.x,
      bottom: rect.bottom - coords.y
    } : {
      left: 0,
      top: 0,
      right: 0,
      bottom: 0
    };
  }

  function makeModifier(module, name) {
    var defaults = module.defaults;
    var methods = {
      start: module.start,
      set: module.set,
      beforeEnd: module.beforeEnd,
      stop: module.stop
    };
    var modifier = function modifier(_options) {
      var options = _options || {};
      options.enabled = options.enabled !== false;

      // add missing defaults to options
      for (var prop in defaults) {
        if (!(prop in options)) {
          options[prop] = defaults[prop];
        }
      }
      var m = {
        options: options,
        methods: methods,
        name: name,
        enable: function enable() {
          options.enabled = true;
          return m;
        },
        disable: function disable() {
          options.enabled = false;
          return m;
        }
      };
      return m;
    };
    if (name && typeof name === 'string') {
      // for backwrads compatibility
      modifier._defaults = defaults;
      modifier._methods = methods;
    }
    return modifier;
  }
  function addEventModifiers(_ref) {
    var iEvent = _ref.iEvent,
      interaction = _ref.interaction;
    var result = interaction.modification.result;
    if (result) {
      iEvent.modifiers = result.eventProps;
    }
  }
  var modifiersBase = {
    id: 'modifiers/base',
    before: ['actions'],
    install: function install(scope) {
      scope.defaults.perAction.modifiers = [];
    },
    listeners: {
      'interactions:new': function interactionsNew(_ref2) {
        var interaction = _ref2.interaction;
        interaction.modification = new Modification(interaction);
      },
      'interactions:before-action-start': function interactionsBeforeActionStart(arg) {
        var interaction = arg.interaction;
        var modification = arg.interaction.modification;
        modification.start(arg, interaction.coords.start.page);
        interaction.edges = modification.edges;
        modification.applyToInteraction(arg);
      },
      'interactions:before-action-move': function interactionsBeforeActionMove(arg) {
        var interaction = arg.interaction;
        var modification = interaction.modification;
        var ret = modification.setAndApply(arg);
        interaction.edges = modification.edges;
        return ret;
      },
      'interactions:before-action-end': function interactionsBeforeActionEnd(arg) {
        var interaction = arg.interaction;
        var modification = interaction.modification;
        var ret = modification.beforeEnd(arg);
        interaction.edges = modification.startEdges;
        return ret;
      },
      'interactions:action-start': addEventModifiers,
      'interactions:action-move': addEventModifiers,
      'interactions:action-end': addEventModifiers,
      'interactions:after-action-start': function interactionsAfterActionStart(arg) {
        return arg.interaction.modification.restoreInteractionCoords(arg);
      },
      'interactions:after-action-move': function interactionsAfterActionMove(arg) {
        return arg.interaction.modification.restoreInteractionCoords(arg);
      },
      'interactions:stop': function interactionsStop(arg) {
        return arg.interaction.modification.stop(arg);
      }
    }
  };
  var base = modifiersBase;

  // eslint-disable-next-line @typescript-eslint/no-empty-interface

  var defaults$7 = {
    base: {
      preventDefault: 'auto',
      deltaSource: 'page'
    },
    perAction: {
      enabled: false,
      origin: {
        x: 0,
        y: 0
      }
    },
    actions: {}
  };

  // defined outside of class definition to avoid assignment of undefined during
  // construction

  var InteractEvent = /*#__PURE__*/function (_BaseEvent) {
    _inherits(InteractEvent, _BaseEvent);
    var _super = _createSuper(InteractEvent);
    function InteractEvent(interaction, event, actionName, phase, element, preEnd, type) {
      var _this;
      _classCallCheck(this, InteractEvent);
      _this = _super.call(this, interaction);
      _this.relatedTarget = null;
      _this.screenX = void 0;
      _this.screenY = void 0;
      _this.button = void 0;
      _this.buttons = void 0;
      _this.ctrlKey = void 0;
      _this.shiftKey = void 0;
      _this.altKey = void 0;
      _this.metaKey = void 0;
      _this.page = void 0;
      _this.client = void 0;
      _this.delta = void 0;
      _this.rect = void 0;
      _this.x0 = void 0;
      _this.y0 = void 0;
      _this.t0 = void 0;
      _this.dt = void 0;
      _this.duration = void 0;
      _this.clientX0 = void 0;
      _this.clientY0 = void 0;
      _this.velocity = void 0;
      _this.speed = void 0;
      _this.swipe = void 0;
      // resize
      _this.axes = void 0;
      /** @internal */
      _this.preEnd = void 0;
      element = element || interaction.element;
      var target = interaction.interactable;
      var deltaSource = (target && target.options || defaults$7).deltaSource;
      var origin = getOriginXY(target, element, actionName);
      var starting = phase === 'start';
      var ending = phase === 'end';
      var prevEvent = starting ? _assertThisInitialized(_this) : interaction.prevEvent;
      var coords = starting ? interaction.coords.start : ending ? {
        page: prevEvent.page,
        client: prevEvent.client,
        timeStamp: interaction.coords.cur.timeStamp
      } : interaction.coords.cur;
      _this.page = extend({}, coords.page);
      _this.client = extend({}, coords.client);
      _this.rect = extend({}, interaction.rect);
      _this.timeStamp = coords.timeStamp;
      if (!ending) {
        _this.page.x -= origin.x;
        _this.page.y -= origin.y;
        _this.client.x -= origin.x;
        _this.client.y -= origin.y;
      }
      _this.ctrlKey = event.ctrlKey;
      _this.altKey = event.altKey;
      _this.shiftKey = event.shiftKey;
      _this.metaKey = event.metaKey;
      _this.button = event.button;
      _this.buttons = event.buttons;
      _this.target = element;
      _this.currentTarget = element;
      _this.preEnd = preEnd;
      _this.type = type || actionName + (phase || '');
      _this.interactable = target;
      _this.t0 = starting ? interaction.pointers[interaction.pointers.length - 1].downTime : prevEvent.t0;
      _this.x0 = interaction.coords.start.page.x - origin.x;
      _this.y0 = interaction.coords.start.page.y - origin.y;
      _this.clientX0 = interaction.coords.start.client.x - origin.x;
      _this.clientY0 = interaction.coords.start.client.y - origin.y;
      if (starting || ending) {
        _this.delta = {
          x: 0,
          y: 0
        };
      } else {
        _this.delta = {
          x: _this[deltaSource].x - prevEvent[deltaSource].x,
          y: _this[deltaSource].y - prevEvent[deltaSource].y
        };
      }
      _this.dt = interaction.coords.delta.timeStamp;
      _this.duration = _this.timeStamp - _this.t0;

      // velocity and speed in pixels per second
      _this.velocity = extend({}, interaction.coords.velocity[deltaSource]);
      _this.speed = hypot(_this.velocity.x, _this.velocity.y);
      _this.swipe = ending || phase === 'inertiastart' ? _this.getSwipe() : null;
      return _this;
    }
    _createClass(InteractEvent, [{
      key: "getSwipe",
      value: function getSwipe() {
        var interaction = this._interaction;
        if (interaction.prevEvent.speed < 600 || this.timeStamp - interaction.prevEvent.timeStamp > 150) {
          return null;
        }
        var angle = 180 * Math.atan2(interaction.prevEvent.velocityY, interaction.prevEvent.velocityX) / Math.PI;
        var overlap = 22.5;
        if (angle < 0) {
          angle += 360;
        }
        var left = 135 - overlap <= angle && angle < 225 + overlap;
        var up = 225 - overlap <= angle && angle < 315 + overlap;
        var right = !left && (315 - overlap <= angle || angle < 45 + overlap);
        var down = !up && 45 - overlap <= angle && angle < 135 + overlap;
        return {
          up: up,
          down: down,
          left: left,
          right: right,
          angle: angle,
          speed: interaction.prevEvent.speed,
          velocity: {
            x: interaction.prevEvent.velocityX,
            y: interaction.prevEvent.velocityY
          }
        };
      }
    }, {
      key: "preventDefault",
      value: function preventDefault() {}

      /**
       * Don't call listeners on the remaining targets
       */
    }, {
      key: "stopImmediatePropagation",
      value: function stopImmediatePropagation() {
        this.immediatePropagationStopped = this.propagationStopped = true;
      }

      /**
       * Don't call any other listeners (even on the current target)
       */
    }, {
      key: "stopPropagation",
      value: function stopPropagation() {
        this.propagationStopped = true;
      }
    }]);
    return InteractEvent;
  }(BaseEvent);

  // getters and setters defined here to support typescript 3.6 and below which
  // don't support getter and setters in .d.ts files
  Object.defineProperties(InteractEvent.prototype, {
    pageX: {
      get: function get() {
        return this.page.x;
      },
      set: function set(value) {
        this.page.x = value;
      }
    },
    pageY: {
      get: function get() {
        return this.page.y;
      },
      set: function set(value) {
        this.page.y = value;
      }
    },
    clientX: {
      get: function get() {
        return this.client.x;
      },
      set: function set(value) {
        this.client.x = value;
      }
    },
    clientY: {
      get: function get() {
        return this.client.y;
      },
      set: function set(value) {
        this.client.y = value;
      }
    },
    dx: {
      get: function get() {
        return this.delta.x;
      },
      set: function set(value) {
        this.delta.x = value;
      }
    },
    dy: {
      get: function get() {
        return this.delta.y;
      },
      set: function set(value) {
        this.delta.y = value;
      }
    },
    velocityX: {
      get: function get() {
        return this.velocity.x;
      },
      set: function set(value) {
        this.velocity.x = value;
      }
    },
    velocityY: {
      get: function get() {
        return this.velocity.y;
      },
      set: function set(value) {
        this.velocity.y = value;
      }
    }
  });

  var PointerInfo = /*#__PURE__*/_createClass(function PointerInfo(id, pointer, event, downTime, downTarget) {
    _classCallCheck(this, PointerInfo);
    this.id = void 0;
    this.pointer = void 0;
    this.event = void 0;
    this.downTime = void 0;
    this.downTarget = void 0;
    this.id = id;
    this.pointer = pointer;
    this.event = event;
    this.downTime = downTime;
    this.downTarget = downTarget;
  });

  var _ProxyValues = /*#__PURE__*/function (_ProxyValues) {
    _ProxyValues["interactable"] = "";
    _ProxyValues["element"] = "";
    _ProxyValues["prepared"] = "";
    _ProxyValues["pointerIsDown"] = "";
    _ProxyValues["pointerWasMoved"] = "";
    _ProxyValues["_proxy"] = "";
    return _ProxyValues;
  }({});
  var _ProxyMethods = /*#__PURE__*/function (_ProxyMethods) {
    _ProxyMethods["start"] = "";
    _ProxyMethods["move"] = "";
    _ProxyMethods["end"] = "";
    _ProxyMethods["stop"] = "";
    _ProxyMethods["interacting"] = "";
    return _ProxyMethods;
  }({});
  var idCounter = 0;
  var Interaction = /*#__PURE__*/function () {
    function Interaction(_ref) {
      var _this = this;
      var pointerType = _ref.pointerType,
        scopeFire = _ref.scopeFire;
      _classCallCheck(this, Interaction);
      /** current interactable being interacted with */
      this.interactable = null;
      /** the target element of the interactable */
      this.element = null;
      this.rect = null;
      /** @internal */
      this._rects = void 0;
      /** @internal */
      this.edges = null;
      /** @internal */
      this._scopeFire = void 0;
      // action that's ready to be fired on next move event
      this.prepared = {
        name: null,
        axis: null,
        edges: null
      };
      this.pointerType = void 0;
      /** @internal keep track of added pointers */
      this.pointers = [];
      /** @internal pointerdown/mousedown/touchstart event */
      this.downEvent = null;
      /** @internal */
      this.downPointer = {};
      /** @internal */
      this._latestPointer = {
        pointer: null,
        event: null,
        eventTarget: null
      };
      /** @internal */
      this.prevEvent = null;
      this.pointerIsDown = false;
      this.pointerWasMoved = false;
      /** @internal */
      this._interacting = false;
      /** @internal */
      this._ending = false;
      /** @internal */
      this._stopped = true;
      /** @internal */
      this._proxy = void 0;
      /** @internal */
      this.simulation = null;
      this.doMove = warnOnce(function (signalArg) {
        this.move(signalArg);
      }, 'The interaction.doMove() method has been renamed to interaction.move()');
      this.coords = {
        // Starting InteractEvent pointer coordinates
        start: newCoords(),
        // Previous native pointer move event coordinates
        prev: newCoords(),
        // current native pointer move event coordinates
        cur: newCoords(),
        // Change in coordinates and time of the pointer
        delta: newCoords(),
        // pointer velocity
        velocity: newCoords()
      };
      /** @internal */
      this._id = idCounter++;
      this._scopeFire = scopeFire;
      this.pointerType = pointerType;
      var that = this;
      this._proxy = {};
      var _loop = function _loop(key) {
        Object.defineProperty(_this._proxy, key, {
          get: function get() {
            return that[key];
          }
        });
      };
      for (var key in _ProxyValues) {
        _loop(key);
      }
      var _loop2 = function _loop2(_key) {
        Object.defineProperty(_this._proxy, _key, {
          value: function value() {
            return that[_key].apply(that, arguments);
          }
        });
      };
      for (var _key in _ProxyMethods) {
        _loop2(_key);
      }
      this._scopeFire('interactions:new', {
        interaction: this
      });
    }
    _createClass(Interaction, [{
      key: "pointerMoveTolerance",
      get: /** @internal */function get() {
        return 1;
      }
    }, {
      key: "pointerDown",
      value: function pointerDown(pointer, event, eventTarget) {
        var pointerIndex = this.updatePointer(pointer, event, eventTarget, true);
        var pointerInfo = this.pointers[pointerIndex];
        this._scopeFire('interactions:down', {
          pointer: pointer,
          event: event,
          eventTarget: eventTarget,
          pointerIndex: pointerIndex,
          pointerInfo: pointerInfo,
          type: 'down',
          interaction: this
        });
      }

      /**
       * ```js
       * interact(target)
       *   .draggable({
       *     // disable the default drag start by down->move
       *     manualStart: true
       *   })
       *   // start dragging after the user holds the pointer down
       *   .on('hold', function (event) {
       *     var interaction = event.interaction
       *
       *     if (!interaction.interacting()) {
       *       interaction.start({ name: 'drag' },
       *                         event.interactable,
       *                         event.currentTarget)
       *     }
       * })
       * ```
       *
       * Start an action with the given Interactable and Element as tartgets. The
       * action must be enabled for the target Interactable and an appropriate
       * number of pointers must be held down - 1 for drag/resize, 2 for gesture.
       *
       * Use it with `interactable.<action>able({ manualStart: false })` to always
       * [start actions manually](https://github.com/taye/interact.js/issues/114)
       *
       * @param action - The action to be performed - drag, resize, etc.
       * @param target - The Interactable to target
       * @param element - The DOM Element to target
       * @returns Whether the interaction was successfully started
       */
    }, {
      key: "start",
      value: function start(action, interactable, element) {
        if (this.interacting() || !this.pointerIsDown || this.pointers.length < (action.name === 'gesture' ? 2 : 1) || !interactable.options[action.name].enabled) {
          return false;
        }
        copyAction(this.prepared, action);
        this.interactable = interactable;
        this.element = element;
        this.rect = interactable.getRect(element);
        this.edges = this.prepared.edges ? extend({}, this.prepared.edges) : {
          left: true,
          right: true,
          top: true,
          bottom: true
        };
        this._stopped = false;
        this._interacting = this._doPhase({
          interaction: this,
          event: this.downEvent,
          phase: 'start'
        }) && !this._stopped;
        return this._interacting;
      }
    }, {
      key: "pointerMove",
      value: function pointerMove(pointer, event, eventTarget) {
        if (!this.simulation && !(this.modification && this.modification.endResult)) {
          this.updatePointer(pointer, event, eventTarget, false);
        }
        var duplicateMove = this.coords.cur.page.x === this.coords.prev.page.x && this.coords.cur.page.y === this.coords.prev.page.y && this.coords.cur.client.x === this.coords.prev.client.x && this.coords.cur.client.y === this.coords.prev.client.y;
        var dx;
        var dy;

        // register movement greater than pointerMoveTolerance
        if (this.pointerIsDown && !this.pointerWasMoved) {
          dx = this.coords.cur.client.x - this.coords.start.client.x;
          dy = this.coords.cur.client.y - this.coords.start.client.y;
          this.pointerWasMoved = hypot(dx, dy) > this.pointerMoveTolerance;
        }
        var pointerIndex = this.getPointerIndex(pointer);
        var signalArg = {
          pointer: pointer,
          pointerIndex: pointerIndex,
          pointerInfo: this.pointers[pointerIndex],
          event: event,
          type: 'move',
          eventTarget: eventTarget,
          dx: dx,
          dy: dy,
          duplicate: duplicateMove,
          interaction: this
        };
        if (!duplicateMove) {
          // set pointer coordinate, time changes and velocity
          setCoordVelocity(this.coords.velocity, this.coords.delta);
        }
        this._scopeFire('interactions:move', signalArg);
        if (!duplicateMove && !this.simulation) {
          // if interacting, fire an 'action-move' signal etc
          if (this.interacting()) {
            signalArg.type = null;
            this.move(signalArg);
          }
          if (this.pointerWasMoved) {
            copyCoords(this.coords.prev, this.coords.cur);
          }
        }
      }

      /**
       * ```js
       * interact(target)
       *   .draggable(true)
       *   .on('dragmove', function (event) {
       *     if (someCondition) {
       *       // change the snap settings
       *       event.interactable.draggable({ snap: { targets: [] }})
       *       // fire another move event with re-calculated snap
       *       event.interaction.move()
       *     }
       *   })
       * ```
       *
       * Force a move of the current action at the same coordinates. Useful if
       * snap/restrict has been changed and you want a movement with the new
       * settings.
       */
    }, {
      key: "move",
      value: function move(signalArg) {
        if (!signalArg || !signalArg.event) {
          setZeroCoords(this.coords.delta);
        }
        signalArg = extend({
          pointer: this._latestPointer.pointer,
          event: this._latestPointer.event,
          eventTarget: this._latestPointer.eventTarget,
          interaction: this
        }, signalArg || {});
        signalArg.phase = 'move';
        this._doPhase(signalArg);
      }

      /**
       * @internal
       * End interact move events and stop auto-scroll unless simulation is running
       */
    }, {
      key: "pointerUp",
      value: function pointerUp(pointer, event, eventTarget, curEventTarget) {
        var pointerIndex = this.getPointerIndex(pointer);
        if (pointerIndex === -1) {
          pointerIndex = this.updatePointer(pointer, event, eventTarget, false);
        }
        var type = /cancel$/i.test(event.type) ? 'cancel' : 'up';
        this._scopeFire("interactions:".concat(type), {
          pointer: pointer,
          pointerIndex: pointerIndex,
          pointerInfo: this.pointers[pointerIndex],
          event: event,
          eventTarget: eventTarget,
          type: type,
          curEventTarget: curEventTarget,
          interaction: this
        });
        if (!this.simulation) {
          this.end(event);
        }
        this.removePointer(pointer, event);
      }

      /** @internal */
    }, {
      key: "documentBlur",
      value: function documentBlur(event) {
        this.end(event);
        this._scopeFire('interactions:blur', {
          event: event,
          type: 'blur',
          interaction: this
        });
      }

      /**
       * ```js
       * interact(target)
       *   .draggable(true)
       *   .on('move', function (event) {
       *     if (event.pageX > 1000) {
       *       // end the current action
       *       event.interaction.end()
       *       // stop all further listeners from being called
       *       event.stopImmediatePropagation()
       *     }
       *   })
       * ```
       */
    }, {
      key: "end",
      value: function end(event) {
        this._ending = true;
        event = event || this._latestPointer.event;
        var endPhaseResult;
        if (this.interacting()) {
          endPhaseResult = this._doPhase({
            event: event,
            interaction: this,
            phase: 'end'
          });
        }
        this._ending = false;
        if (endPhaseResult === true) {
          this.stop();
        }
      }
    }, {
      key: "currentAction",
      value: function currentAction() {
        return this._interacting ? this.prepared.name : null;
      }
    }, {
      key: "interacting",
      value: function interacting() {
        return this._interacting;
      }
    }, {
      key: "stop",
      value: function stop() {
        this._scopeFire('interactions:stop', {
          interaction: this
        });
        this.interactable = this.element = null;
        this._interacting = false;
        this._stopped = true;
        this.prepared.name = this.prevEvent = null;
      }

      /** @internal */
    }, {
      key: "getPointerIndex",
      value: function getPointerIndex(pointer) {
        var pointerId = getPointerId(pointer);

        // mouse and pen interactions may have only one pointer
        return this.pointerType === 'mouse' || this.pointerType === 'pen' ? this.pointers.length - 1 : findIndex(this.pointers, function (curPointer) {
          return curPointer.id === pointerId;
        });
      }

      /** @internal */
    }, {
      key: "getPointerInfo",
      value: function getPointerInfo(pointer) {
        return this.pointers[this.getPointerIndex(pointer)];
      }

      /** @internal */
    }, {
      key: "updatePointer",
      value: function updatePointer(pointer, event, eventTarget, down) {
        var id = getPointerId(pointer);
        var pointerIndex = this.getPointerIndex(pointer);
        var pointerInfo = this.pointers[pointerIndex];
        down = down === false ? false : down || /(down|start)$/i.test(event.type);
        if (!pointerInfo) {
          pointerInfo = new PointerInfo(id, pointer, event, null, null);
          pointerIndex = this.pointers.length;
          this.pointers.push(pointerInfo);
        } else {
          pointerInfo.pointer = pointer;
        }
        setCoords(this.coords.cur, this.pointers.map(function (p) {
          return p.pointer;
        }), this._now());
        setCoordDeltas(this.coords.delta, this.coords.prev, this.coords.cur);
        if (down) {
          this.pointerIsDown = true;
          pointerInfo.downTime = this.coords.cur.timeStamp;
          pointerInfo.downTarget = eventTarget;
          pointerExtend(this.downPointer, pointer);
          if (!this.interacting()) {
            copyCoords(this.coords.start, this.coords.cur);
            copyCoords(this.coords.prev, this.coords.cur);
            this.downEvent = event;
            this.pointerWasMoved = false;
          }
        }
        this._updateLatestPointer(pointer, event, eventTarget);
        this._scopeFire('interactions:update-pointer', {
          pointer: pointer,
          event: event,
          eventTarget: eventTarget,
          down: down,
          pointerInfo: pointerInfo,
          pointerIndex: pointerIndex,
          interaction: this
        });
        return pointerIndex;
      }

      /** @internal */
    }, {
      key: "removePointer",
      value: function removePointer(pointer, event) {
        var pointerIndex = this.getPointerIndex(pointer);
        if (pointerIndex === -1) return;
        var pointerInfo = this.pointers[pointerIndex];
        this._scopeFire('interactions:remove-pointer', {
          pointer: pointer,
          event: event,
          eventTarget: null,
          pointerIndex: pointerIndex,
          pointerInfo: pointerInfo,
          interaction: this
        });
        this.pointers.splice(pointerIndex, 1);
        this.pointerIsDown = false;
      }

      /** @internal */
    }, {
      key: "_updateLatestPointer",
      value: function _updateLatestPointer(pointer, event, eventTarget) {
        this._latestPointer.pointer = pointer;
        this._latestPointer.event = event;
        this._latestPointer.eventTarget = eventTarget;
      }
    }, {
      key: "destroy",
      value: function destroy() {
        this._latestPointer.pointer = null;
        this._latestPointer.event = null;
        this._latestPointer.eventTarget = null;
      }

      /** @internal */
    }, {
      key: "_createPreparedEvent",
      value: function _createPreparedEvent(event, phase, preEnd, type) {
        return new InteractEvent(this, event, this.prepared.name, phase, this.element, preEnd, type);
      }

      /** @internal */
    }, {
      key: "_fireEvent",
      value: function _fireEvent(iEvent) {
        var _this$interactable;
        (_this$interactable = this.interactable) == null ? void 0 : _this$interactable.fire(iEvent);
        if (!this.prevEvent || iEvent.timeStamp >= this.prevEvent.timeStamp) {
          this.prevEvent = iEvent;
        }
      }

      /** @internal */
    }, {
      key: "_doPhase",
      value: function _doPhase(signalArg) {
        var event = signalArg.event,
          phase = signalArg.phase,
          preEnd = signalArg.preEnd,
          type = signalArg.type;
        var rect = this.rect;
        if (rect && phase === 'move') {
          // update the rect changes due to pointer move
          addEdges(this.edges, rect, this.coords.delta[this.interactable.options.deltaSource]);
          rect.width = rect.right - rect.left;
          rect.height = rect.bottom - rect.top;
        }
        var beforeResult = this._scopeFire("interactions:before-action-".concat(phase), signalArg);
        if (beforeResult === false) {
          return false;
        }
        var iEvent = signalArg.iEvent = this._createPreparedEvent(event, phase, preEnd, type);
        this._scopeFire("interactions:action-".concat(phase), signalArg);
        if (phase === 'start') {
          this.prevEvent = iEvent;
        }
        this._fireEvent(iEvent);
        this._scopeFire("interactions:after-action-".concat(phase), signalArg);
        return true;
      }

      /** @internal */
    }, {
      key: "_now",
      value: function _now() {
        return Date.now();
      }
    }]);
    return Interaction;
  }();

  _ProxyMethods.offsetBy = '';
  function addTotal(interaction) {
    if (!interaction.pointerIsDown) {
      return;
    }
    addToCoords(interaction.coords.cur, interaction.offset.total);
    interaction.offset.pending.x = 0;
    interaction.offset.pending.y = 0;
  }
  function beforeAction(_ref) {
    var interaction = _ref.interaction;
    applyPending(interaction);
  }
  function beforeEnd(_ref2) {
    var interaction = _ref2.interaction;
    var hadPending = applyPending(interaction);
    if (!hadPending) return;
    interaction.move({
      offset: true
    });
    interaction.end();
    return false;
  }
  function end(_ref3) {
    var interaction = _ref3.interaction;
    interaction.offset.total.x = 0;
    interaction.offset.total.y = 0;
    interaction.offset.pending.x = 0;
    interaction.offset.pending.y = 0;
  }
  function applyPending(interaction) {
    if (!hasPending(interaction)) {
      return false;
    }
    var pending = interaction.offset.pending;
    addToCoords(interaction.coords.cur, pending);
    addToCoords(interaction.coords.delta, pending);
    addEdges(interaction.edges, interaction.rect, pending);
    pending.x = 0;
    pending.y = 0;
    return true;
  }
  function offsetBy(_ref4) {
    var x = _ref4.x,
      y = _ref4.y;
    this.offset.pending.x += x;
    this.offset.pending.y += y;
    this.offset.total.x += x;
    this.offset.total.y += y;
  }
  function addToCoords(_ref5, _ref6) {
    var page = _ref5.page,
      client = _ref5.client;
    var x = _ref6.x,
      y = _ref6.y;
    page.x += x;
    page.y += y;
    client.x += x;
    client.y += y;
  }
  function hasPending(interaction) {
    return !!(interaction.offset.pending.x || interaction.offset.pending.y);
  }
  var offset = {
    id: 'offset',
    before: ['modifiers', 'pointer-events', 'actions', 'inertia'],
    install: function install(scope) {
      scope.Interaction.prototype.offsetBy = offsetBy;
    },
    listeners: {
      'interactions:new': function interactionsNew(_ref7) {
        var interaction = _ref7.interaction;
        interaction.offset = {
          total: {
            x: 0,
            y: 0
          },
          pending: {
            x: 0,
            y: 0
          }
        };
      },
      'interactions:update-pointer': function interactionsUpdatePointer(_ref8) {
        var interaction = _ref8.interaction;
        return addTotal(interaction);
      },
      'interactions:before-action-start': beforeAction,
      'interactions:before-action-move': beforeAction,
      'interactions:before-action-end': beforeEnd,
      'interactions:stop': end
    }
  };
  var offset$1 = offset;

  function install$6(scope) {
    var defaults = scope.defaults;
    scope.usePlugin(offset$1);
    scope.usePlugin(base);
    scope.actions.phases.inertiastart = true;
    scope.actions.phases.resume = true;
    defaults.perAction.inertia = {
      enabled: false,
      resistance: 10,
      // the lambda in exponential decay
      minSpeed: 100,
      // target speed must be above this for inertia to start
      endSpeed: 10,
      // the speed at which inertia is slow enough to stop
      allowResume: true,
      // allow resuming an action in inertia phase
      smoothEndDuration: 300 // animate to snap/restrict endOnly if there's no inertia
    };
  }
  var InertiaState = /*#__PURE__*/function () {
    function InertiaState(interaction) {
      _classCallCheck(this, InertiaState);
      this.active = false;
      this.isModified = false;
      this.smoothEnd = false;
      this.allowResume = false;
      this.modification = void 0;
      this.modifierCount = 0;
      this.modifierArg = void 0;
      this.startCoords = void 0;
      this.t0 = 0;
      this.v0 = 0;
      this.te = 0;
      this.targetOffset = void 0;
      this.modifiedOffset = void 0;
      this.currentOffset = void 0;
      this.lambda_v0 = 0;
      // eslint-disable-line camelcase
      this.one_ve_v0 = 0;
      // eslint-disable-line camelcase
      this.timeout = void 0;
      this.interaction = void 0;
      this.interaction = interaction;
    }
    _createClass(InertiaState, [{
      key: "start",
      value: function start(event) {
        var interaction = this.interaction;
        var options = getOptions$1(interaction);
        if (!options || !options.enabled) {
          return false;
        }
        var velocityClient = interaction.coords.velocity.client;
        var pointerSpeed = hypot(velocityClient.x, velocityClient.y);
        var modification = this.modification || (this.modification = new Modification(interaction));
        modification.copyFrom(interaction.modification);
        this.t0 = interaction._now();
        this.allowResume = options.allowResume;
        this.v0 = pointerSpeed;
        this.currentOffset = {
          x: 0,
          y: 0
        };
        this.startCoords = interaction.coords.cur.page;
        this.modifierArg = modification.fillArg({
          pageCoords: this.startCoords,
          preEnd: true,
          phase: 'inertiastart'
        });
        var thrown = this.t0 - interaction.coords.cur.timeStamp < 50 && pointerSpeed > options.minSpeed && pointerSpeed > options.endSpeed;
        if (thrown) {
          this.startInertia();
        } else {
          modification.result = modification.setAll(this.modifierArg);
          if (!modification.result.changed) {
            return false;
          }
          this.startSmoothEnd();
        }

        // force modification change
        interaction.modification.result.rect = null;

        // bring inertiastart event to the target coords
        interaction.offsetBy(this.targetOffset);
        interaction._doPhase({
          interaction: interaction,
          event: event,
          phase: 'inertiastart'
        });
        interaction.offsetBy({
          x: -this.targetOffset.x,
          y: -this.targetOffset.y
        });
        // force modification change
        interaction.modification.result.rect = null;
        this.active = true;
        interaction.simulation = this;
        return true;
      }
    }, {
      key: "startInertia",
      value: function startInertia() {
        var _this = this;
        var startVelocity = this.interaction.coords.velocity.client;
        var options = getOptions$1(this.interaction);
        var lambda = options.resistance;
        var inertiaDur = -Math.log(options.endSpeed / this.v0) / lambda;
        this.targetOffset = {
          x: (startVelocity.x - inertiaDur) / lambda,
          y: (startVelocity.y - inertiaDur) / lambda
        };
        this.te = inertiaDur;
        this.lambda_v0 = lambda / this.v0;
        this.one_ve_v0 = 1 - options.endSpeed / this.v0;
        var modification = this.modification,
          modifierArg = this.modifierArg;
        modifierArg.pageCoords = {
          x: this.startCoords.x + this.targetOffset.x,
          y: this.startCoords.y + this.targetOffset.y
        };
        modification.result = modification.setAll(modifierArg);
        if (modification.result.changed) {
          this.isModified = true;
          this.modifiedOffset = {
            x: this.targetOffset.x + modification.result.delta.x,
            y: this.targetOffset.y + modification.result.delta.y
          };
        }
        this.onNextFrame(function () {
          return _this.inertiaTick();
        });
      }
    }, {
      key: "startSmoothEnd",
      value: function startSmoothEnd() {
        var _this2 = this;
        this.smoothEnd = true;
        this.isModified = true;
        this.targetOffset = {
          x: this.modification.result.delta.x,
          y: this.modification.result.delta.y
        };
        this.onNextFrame(function () {
          return _this2.smoothEndTick();
        });
      }
    }, {
      key: "onNextFrame",
      value: function onNextFrame(tickFn) {
        var _this3 = this;
        this.timeout = raf.request(function () {
          if (_this3.active) {
            tickFn();
          }
        });
      }
    }, {
      key: "inertiaTick",
      value: function inertiaTick() {
        var _this4 = this;
        var interaction = this.interaction;
        var options = getOptions$1(interaction);
        var lambda = options.resistance;
        var t = (interaction._now() - this.t0) / 1000;
        if (t < this.te) {
          var progress = 1 - (Math.exp(-lambda * t) - this.lambda_v0) / this.one_ve_v0;
          var newOffset;
          if (this.isModified) {
            newOffset = getQuadraticCurvePoint(0, 0, this.targetOffset.x, this.targetOffset.y, this.modifiedOffset.x, this.modifiedOffset.y, progress);
          } else {
            newOffset = {
              x: this.targetOffset.x * progress,
              y: this.targetOffset.y * progress
            };
          }
          var delta = {
            x: newOffset.x - this.currentOffset.x,
            y: newOffset.y - this.currentOffset.y
          };
          this.currentOffset.x += delta.x;
          this.currentOffset.y += delta.y;
          interaction.offsetBy(delta);
          interaction.move();
          this.onNextFrame(function () {
            return _this4.inertiaTick();
          });
        } else {
          interaction.offsetBy({
            x: this.modifiedOffset.x - this.currentOffset.x,
            y: this.modifiedOffset.y - this.currentOffset.y
          });
          this.end();
        }
      }
    }, {
      key: "smoothEndTick",
      value: function smoothEndTick() {
        var _this5 = this;
        var interaction = this.interaction;
        var t = interaction._now() - this.t0;
        var _getOptions = getOptions$1(interaction),
          duration = _getOptions.smoothEndDuration;
        if (t < duration) {
          var newOffset = {
            x: easeOutQuad(t, 0, this.targetOffset.x, duration),
            y: easeOutQuad(t, 0, this.targetOffset.y, duration)
          };
          var delta = {
            x: newOffset.x - this.currentOffset.x,
            y: newOffset.y - this.currentOffset.y
          };
          this.currentOffset.x += delta.x;
          this.currentOffset.y += delta.y;
          interaction.offsetBy(delta);
          interaction.move({
            skipModifiers: this.modifierCount
          });
          this.onNextFrame(function () {
            return _this5.smoothEndTick();
          });
        } else {
          interaction.offsetBy({
            x: this.targetOffset.x - this.currentOffset.x,
            y: this.targetOffset.y - this.currentOffset.y
          });
          this.end();
        }
      }
    }, {
      key: "resume",
      value: function resume(_ref) {
        var pointer = _ref.pointer,
          event = _ref.event,
          eventTarget = _ref.eventTarget;
        var interaction = this.interaction;

        // undo inertia changes to interaction coords
        interaction.offsetBy({
          x: -this.currentOffset.x,
          y: -this.currentOffset.y
        });

        // update pointer at pointer down position
        interaction.updatePointer(pointer, event, eventTarget, true);

        // fire resume signals and event
        interaction._doPhase({
          interaction: interaction,
          event: event,
          phase: 'resume'
        });
        copyCoords(interaction.coords.prev, interaction.coords.cur);
        this.stop();
      }
    }, {
      key: "end",
      value: function end() {
        this.interaction.move();
        this.interaction.end();
        this.stop();
      }
    }, {
      key: "stop",
      value: function stop() {
        this.active = this.smoothEnd = false;
        this.interaction.simulation = null;
        raf.cancel(this.timeout);
      }
    }]);
    return InertiaState;
  }();
  function start$6(_ref2) {
    var interaction = _ref2.interaction,
      event = _ref2.event;
    if (!interaction._interacting || interaction.simulation) {
      return null;
    }
    var started = interaction.inertia.start(event);

    // prevent action end if inertia or smoothEnd
    return started ? false : null;
  }

  // Check if the down event hits the current inertia target
  // control should be return to the user
  function resume(arg) {
    var interaction = arg.interaction,
      eventTarget = arg.eventTarget;
    var state = interaction.inertia;
    if (!state.active) return;
    var element = eventTarget;

    // climb up the DOM tree from the event target
    while (is.element(element)) {
      // if interaction element is the current inertia target element
      if (element === interaction.element) {
        state.resume(arg);
        break;
      }
      element = parentNode(element);
    }
  }
  function stop(_ref3) {
    var interaction = _ref3.interaction;
    var state = interaction.inertia;
    if (state.active) {
      state.stop();
    }
  }
  function getOptions$1(_ref4) {
    var interactable = _ref4.interactable,
      prepared = _ref4.prepared;
    return interactable && interactable.options && prepared.name && interactable.options[prepared.name].inertia;
  }
  var inertia = {
    id: 'inertia',
    before: ['modifiers', 'actions'],
    install: install$6,
    listeners: {
      'interactions:new': function interactionsNew(_ref5) {
        var interaction = _ref5.interaction;
        interaction.inertia = new InertiaState(interaction);
      },
      'interactions:before-action-end': start$6,
      'interactions:down': resume,
      'interactions:stop': stop,
      'interactions:before-action-resume': function interactionsBeforeActionResume(arg) {
        var modification = arg.interaction.modification;
        modification.stop(arg);
        modification.start(arg, arg.interaction.coords.cur.page);
        modification.applyToInteraction(arg);
      },
      'interactions:before-action-inertiastart': function interactionsBeforeActionInertiastart(arg) {
        return arg.interaction.modification.setAndApply(arg);
      },
      'interactions:action-resume': addEventModifiers,
      'interactions:action-inertiastart': addEventModifiers,
      'interactions:after-action-inertiastart': function interactionsAfterActionInertiastart(arg) {
        return arg.interaction.modification.restoreInteractionCoords(arg);
      },
      'interactions:after-action-resume': function interactionsAfterActionResume(arg) {
        return arg.interaction.modification.restoreInteractionCoords(arg);
      }
    }
  };

  // http://stackoverflow.com/a/5634528/2280888
  function _getQBezierValue(t, p1, p2, p3) {
    var iT = 1 - t;
    return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
  }
  function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
    return {
      x: _getQBezierValue(position, startX, cpX, endX),
      y: _getQBezierValue(position, startY, cpY, endY)
    };
  }

  // http://gizma.com/easing/
  function easeOutQuad(t, b, c, d) {
    t /= d;
    return -c * t * (t - 2) + b;
  }
  var inertia$1 = inertia;

  function fireUntilImmediateStopped(event, listeners) {
    for (var _i2 = 0; _i2 < listeners.length; _i2++) {
      var listener = listeners[_i2];
      if (event.immediatePropagationStopped) {
        break;
      }
      listener(event);
    }
  }
  var Eventable = /*#__PURE__*/function () {
    function Eventable(options) {
      _classCallCheck(this, Eventable);
      this.options = void 0;
      this.types = {};
      this.propagationStopped = false;
      this.immediatePropagationStopped = false;
      this.global = void 0;
      this.options = extend({}, options || {});
    }
    _createClass(Eventable, [{
      key: "fire",
      value: function fire(event) {
        var listeners;
        var global = this.global;

        // Interactable#on() listeners
        // tslint:disable no-conditional-assignment
        if (listeners = this.types[event.type]) {
          fireUntilImmediateStopped(event, listeners);
        }

        // interact.on() listeners
        if (!event.propagationStopped && global && (listeners = global[event.type])) {
          fireUntilImmediateStopped(event, listeners);
        }
      }
    }, {
      key: "on",
      value: function on(type, listener) {
        var listeners = normalize(type, listener);
        for (type in listeners) {
          this.types[type] = merge(this.types[type] || [], listeners[type]);
        }
      }
    }, {
      key: "off",
      value: function off(type, listener) {
        var listeners = normalize(type, listener);
        for (type in listeners) {
          var eventList = this.types[type];
          if (!eventList || !eventList.length) {
            continue;
          }
          for (var _i4 = 0, _listeners$type2 = listeners[type]; _i4 < _listeners$type2.length; _i4++) {
            var subListener = _listeners$type2[_i4];
            var _index = eventList.indexOf(subListener);
            if (_index !== -1) {
              eventList.splice(_index, 1);
            }
          }
        }
      }
    }, {
      key: "getRect",
      value: function getRect(_element) {
        return null;
      }
    }]);
    return Eventable;
  }();

  function install$5(scope) {
    var _scope$document;
    var targets = [];
    var delegatedEvents = {};
    var documents = [];
    var eventsMethods = {
      add: add,
      remove: remove,
      addDelegate: addDelegate,
      removeDelegate: removeDelegate,
      delegateListener: delegateListener,
      delegateUseCapture: delegateUseCapture,
      delegatedEvents: delegatedEvents,
      documents: documents,
      targets: targets,
      supportsOptions: false,
      supportsPassive: false
    };

    // check if browser supports passive events and options arg
    (_scope$document = scope.document) == null ? void 0 : _scope$document.createElement('div').addEventListener('test', null, {
      get capture() {
        return eventsMethods.supportsOptions = true;
      },
      get passive() {
        return eventsMethods.supportsPassive = true;
      }
    });
    scope.events = eventsMethods;
    function add(eventTarget, type, listener, optionalArg) {
      if (!eventTarget.addEventListener) return;
      var options = getOptions(optionalArg);
      var target = find(targets, function (t) {
        return t.eventTarget === eventTarget;
      });
      if (!target) {
        target = {
          eventTarget: eventTarget,
          events: {}
        };
        targets.push(target);
      }
      if (!target.events[type]) {
        target.events[type] = [];
      }
      if (!find(target.events[type], function (l) {
        return l.func === listener && optionsMatch(l.options, options);
      })) {
        eventTarget.addEventListener(type, listener, eventsMethods.supportsOptions ? options : options.capture);
        target.events[type].push({
          func: listener,
          options: options
        });
      }
    }
    function remove(eventTarget, type, listener, optionalArg) {
      if (!eventTarget.addEventListener || !eventTarget.removeEventListener) return;
      var targetIndex = findIndex(targets, function (t) {
        return t.eventTarget === eventTarget;
      });
      var target = targets[targetIndex];
      if (!target || !target.events) {
        return;
      }
      if (type === 'all') {
        for (type in target.events) {
          if (target.events.hasOwnProperty(type)) {
            remove(eventTarget, type, 'all');
          }
        }
        return;
      }
      var typeIsEmpty = false;
      var typeListeners = target.events[type];
      if (typeListeners) {
        if (listener === 'all') {
          for (var i = typeListeners.length - 1; i >= 0; i--) {
            var entry = typeListeners[i];
            remove(eventTarget, type, entry.func, entry.options);
          }
          return;
        } else {
          var options = getOptions(optionalArg);
          for (var _i = 0; _i < typeListeners.length; _i++) {
            var _entry = typeListeners[_i];
            if (_entry.func === listener && optionsMatch(_entry.options, options)) {
              eventTarget.removeEventListener(type, listener, eventsMethods.supportsOptions ? options : options.capture);
              typeListeners.splice(_i, 1);
              if (typeListeners.length === 0) {
                delete target.events[type];
                typeIsEmpty = true;
              }
              break;
            }
          }
        }
      }
      if (typeIsEmpty && !Object.keys(target.events).length) {
        targets.splice(targetIndex, 1);
      }
    }
    function addDelegate(selector, context, type, listener, optionalArg) {
      var options = getOptions(optionalArg);
      if (!delegatedEvents[type]) {
        delegatedEvents[type] = [];

        // add delegate listener functions
        for (var _i3 = 0; _i3 < documents.length; _i3++) {
          var doc = documents[_i3];
          add(doc, type, delegateListener);
          add(doc, type, delegateUseCapture, true);
        }
      }
      var delegates = delegatedEvents[type];
      var delegate = find(delegates, function (d) {
        return d.selector === selector && d.context === context;
      });
      if (!delegate) {
        delegate = {
          selector: selector,
          context: context,
          listeners: []
        };
        delegates.push(delegate);
      }
      delegate.listeners.push({
        func: listener,
        options: options
      });
    }
    function removeDelegate(selector, context, type, listener, optionalArg) {
      var options = getOptions(optionalArg);
      var delegates = delegatedEvents[type];
      var matchFound = false;
      var index;
      if (!delegates) return;

      // count from last index of delegated to 0
      for (index = delegates.length - 1; index >= 0; index--) {
        var cur = delegates[index];
        // look for matching selector and context Node
        if (cur.selector === selector && cur.context === context) {
          var listeners = cur.listeners;

          // each item of the listeners array is an array: [function, capture, passive]
          for (var i = listeners.length - 1; i >= 0; i--) {
            var entry = listeners[i];

            // check if the listener functions and capture and passive flags match
            if (entry.func === listener && optionsMatch(entry.options, options)) {
              // remove the listener from the array of listeners
              listeners.splice(i, 1);

              // if all listeners for this target have been removed
              // remove the target from the delegates array
              if (!listeners.length) {
                delegates.splice(index, 1);

                // remove delegate function from context
                remove(context, type, delegateListener);
                remove(context, type, delegateUseCapture, true);
              }

              // only remove one listener
              matchFound = true;
              break;
            }
          }
          if (matchFound) {
            break;
          }
        }
      }
    }

    // bound to the interactable context when a DOM event
    // listener is added to a selector interactable
    function delegateListener(event, optionalArg) {
      var options = getOptions(optionalArg);
      var fakeEvent = new FakeEvent(event);
      var delegates = delegatedEvents[event.type];
      var _pointerUtils$getEven = getEventTargets(event),
        eventTarget = _pointerUtils$getEven[0];
      var element = eventTarget;

      // climb up document tree looking for selector matches
      while (is.element(element)) {
        for (var i = 0; i < delegates.length; i++) {
          var cur = delegates[i];
          var selector = cur.selector,
            context = cur.context;
          if (matchesSelector(element, selector) && nodeContains(context, eventTarget) && nodeContains(context, element)) {
            var listeners = cur.listeners;
            fakeEvent.currentTarget = element;
            for (var _i5 = 0; _i5 < listeners.length; _i5++) {
              var entry = listeners[_i5];
              if (optionsMatch(entry.options, options)) {
                entry.func(fakeEvent);
              }
            }
          }
        }
        element = parentNode(element);
      }
    }
    function delegateUseCapture(event) {
      return delegateListener.call(this, event, true);
    }

    // for type inferrence
    return eventsMethods;
  }
  var FakeEvent = /*#__PURE__*/function () {
    function FakeEvent(originalEvent) {
      _classCallCheck(this, FakeEvent);
      this.currentTarget = void 0;
      this.originalEvent = void 0;
      this.type = void 0;
      this.originalEvent = originalEvent;
      // duplicate the event so that currentTarget can be changed
      pointerExtend(this, originalEvent);
    }
    _createClass(FakeEvent, [{
      key: "preventOriginalDefault",
      value: function preventOriginalDefault() {
        this.originalEvent.preventDefault();
      }
    }, {
      key: "stopPropagation",
      value: function stopPropagation() {
        this.originalEvent.stopPropagation();
      }
    }, {
      key: "stopImmediatePropagation",
      value: function stopImmediatePropagation() {
        this.originalEvent.stopImmediatePropagation();
      }
    }]);
    return FakeEvent;
  }();
  function getOptions(param) {
    if (!is.object(param)) {
      return {
        capture: !!param,
        passive: false
      };
    }
    return {
      capture: !!param.capture,
      passive: !!param.passive
    };
  }
  function optionsMatch(a, b) {
    if (a === b) return true;
    if (typeof a === 'boolean') return !!b.capture === a && !!b.passive === false;
    return !!a.capture === !!b.capture && !!a.passive === !!b.passive;
  }
  var events = {
    id: 'events',
    install: install$5
  };

  var finder = {
    methodOrder: ['simulationResume', 'mouseOrPen', 'hasPointer', 'idle'],
    search: function search(details) {
      for (var _i2 = 0, _finder$methodOrder2 = finder.methodOrder; _i2 < _finder$methodOrder2.length; _i2++) {
        var method = _finder$methodOrder2[_i2];
        var interaction = finder[method](details);
        if (interaction) {
          return interaction;
        }
      }
      return null;
    },
    // try to resume simulation with a new pointer
    simulationResume: function simulationResume(_ref) {
      var pointerType = _ref.pointerType,
        eventType = _ref.eventType,
        eventTarget = _ref.eventTarget,
        scope = _ref.scope;
      if (!/down|start/i.test(eventType)) {
        return null;
      }
      for (var _i4 = 0, _scope$interactions$l2 = scope.interactions.list; _i4 < _scope$interactions$l2.length; _i4++) {
        var interaction = _scope$interactions$l2[_i4];
        var element = eventTarget;
        if (interaction.simulation && interaction.simulation.allowResume && interaction.pointerType === pointerType) {
          while (element) {
            // if the element is the interaction element
            if (element === interaction.element) {
              return interaction;
            }
            element = parentNode(element);
          }
        }
      }
      return null;
    },
    // if it's a mouse or pen interaction
    mouseOrPen: function mouseOrPen(_ref2) {
      var pointerId = _ref2.pointerId,
        pointerType = _ref2.pointerType,
        eventType = _ref2.eventType,
        scope = _ref2.scope;
      if (pointerType !== 'mouse' && pointerType !== 'pen') {
        return null;
      }
      var firstNonActive;
      for (var _i6 = 0, _scope$interactions$l4 = scope.interactions.list; _i6 < _scope$interactions$l4.length; _i6++) {
        var interaction = _scope$interactions$l4[_i6];
        if (interaction.pointerType === pointerType) {
          // if it's a down event, skip interactions with running simulations
          if (interaction.simulation && !hasPointerId(interaction, pointerId)) {
            continue;
          }

          // if the interaction is active, return it immediately
          if (interaction.interacting()) {
            return interaction;
          }
          // otherwise save it and look for another active interaction
          else if (!firstNonActive) {
            firstNonActive = interaction;
          }
        }
      } // if no active mouse interaction was found use the first inactive mouse
      // interaction
      if (firstNonActive) {
        return firstNonActive;
      }

      // find any mouse or pen interaction.
      // ignore the interaction if the eventType is a *down, and a simulation
      // is active
      for (var _i8 = 0, _scope$interactions$l6 = scope.interactions.list; _i8 < _scope$interactions$l6.length; _i8++) {
        var _interaction = _scope$interactions$l6[_i8];
        if (_interaction.pointerType === pointerType && !(/down/i.test(eventType) && _interaction.simulation)) {
          return _interaction;
        }
      }
      return null;
    },
    // get interaction that has this pointer
    hasPointer: function hasPointer(_ref3) {
      var pointerId = _ref3.pointerId,
        scope = _ref3.scope;
      for (var _i10 = 0, _scope$interactions$l8 = scope.interactions.list; _i10 < _scope$interactions$l8.length; _i10++) {
        var interaction = _scope$interactions$l8[_i10];
        if (hasPointerId(interaction, pointerId)) {
          return interaction;
        }
      }
      return null;
    },
    // get first idle interaction with a matching pointerType
    idle: function idle(_ref4) {
      var pointerType = _ref4.pointerType,
        scope = _ref4.scope;
      for (var _i12 = 0, _scope$interactions$l10 = scope.interactions.list; _i12 < _scope$interactions$l10.length; _i12++) {
        var interaction = _scope$interactions$l10[_i12];
        // if there's already a pointer held down
        if (interaction.pointers.length === 1) {
          var target = interaction.interactable;
          // don't add this pointer if there is a target interactable and it
          // isn't gesturable
          if (target && !(target.options.gesture && target.options.gesture.enabled)) {
            continue;
          }
        }
        // maximum of 2 pointers per interaction
        else if (interaction.pointers.length >= 2) {
          continue;
        }
        if (!interaction.interacting() && pointerType === interaction.pointerType) {
          return interaction;
        }
      }
      return null;
    }
  };
  function hasPointerId(interaction, pointerId) {
    return interaction.pointers.some(function (_ref5) {
      var id = _ref5.id;
      return id === pointerId;
    });
  }
  var finder$1 = finder;

  var methodNames = ['pointerDown', 'pointerMove', 'pointerUp', 'updatePointer', 'removePointer', 'windowBlur'];
  function install$4(scope) {
    var listeners = {};
    for (var _i2 = 0; _i2 < methodNames.length; _i2++) {
      var method = methodNames[_i2];
      listeners[method] = doOnInteractions(method, scope);
    }
    var pEventTypes = browser$1.pEventTypes;
    var docEvents;
    if (domObjects$1.PointerEvent) {
      docEvents = [{
        type: pEventTypes.down,
        listener: releasePointersOnRemovedEls
      }, {
        type: pEventTypes.down,
        listener: listeners.pointerDown
      }, {
        type: pEventTypes.move,
        listener: listeners.pointerMove
      }, {
        type: pEventTypes.up,
        listener: listeners.pointerUp
      }, {
        type: pEventTypes.cancel,
        listener: listeners.pointerUp
      }];
    } else {
      docEvents = [{
        type: 'mousedown',
        listener: listeners.pointerDown
      }, {
        type: 'mousemove',
        listener: listeners.pointerMove
      }, {
        type: 'mouseup',
        listener: listeners.pointerUp
      }, {
        type: 'touchstart',
        listener: releasePointersOnRemovedEls
      }, {
        type: 'touchstart',
        listener: listeners.pointerDown
      }, {
        type: 'touchmove',
        listener: listeners.pointerMove
      }, {
        type: 'touchend',
        listener: listeners.pointerUp
      }, {
        type: 'touchcancel',
        listener: listeners.pointerUp
      }];
    }
    docEvents.push({
      type: 'blur',
      listener: function listener(event) {
        for (var _i4 = 0, _scope$interactions$l2 = scope.interactions.list; _i4 < _scope$interactions$l2.length; _i4++) {
          var interaction = _scope$interactions$l2[_i4];
          interaction.documentBlur(event);
        }
      }
    });

    // for ignoring browser's simulated mouse events
    scope.prevTouchTime = 0;
    scope.Interaction = /*#__PURE__*/function (_InteractionBase) {
      _inherits(_class, _InteractionBase);
      var _super = _createSuper(_class);
      function _class() {
        _classCallCheck(this, _class);
        return _super.apply(this, arguments);
      }
      _createClass(_class, [{
        key: "pointerMoveTolerance",
        get: function get() {
          return scope.interactions.pointerMoveTolerance;
        },
        set: function set(value) {
          scope.interactions.pointerMoveTolerance = value;
        }
      }, {
        key: "_now",
        value: function _now() {
          return scope.now();
        }
      }]);
      return _class;
    }(Interaction);
    scope.interactions = {
      // all active and idle interactions
      list: [],
      new: function _new(options) {
        options.scopeFire = function (name, arg) {
          return scope.fire(name, arg);
        };
        var interaction = new scope.Interaction(options);
        scope.interactions.list.push(interaction);
        return interaction;
      },
      listeners: listeners,
      docEvents: docEvents,
      pointerMoveTolerance: 1
    };
    function releasePointersOnRemovedEls() {
      // for all inactive touch interactions with pointers down
      for (var _i6 = 0, _scope$interactions$l4 = scope.interactions.list; _i6 < _scope$interactions$l4.length; _i6++) {
        var interaction = _scope$interactions$l4[_i6];
        if (!interaction.pointerIsDown || interaction.pointerType !== 'touch' || interaction._interacting) {
          continue;
        }

        // if a pointer is down on an element that is no longer in the DOM tree
        var _loop = function _loop() {
          var pointer = _interaction$pointers2[_i8];
          if (!scope.documents.some(function (_ref) {
            var doc = _ref.doc;
            return nodeContains(doc, pointer.downTarget);
          })) {
            // remove the pointer from the interaction
            interaction.removePointer(pointer.pointer, pointer.event);
          }
        };
        for (var _i8 = 0, _interaction$pointers2 = interaction.pointers; _i8 < _interaction$pointers2.length; _i8++) {
          _loop();
        }
      }
    }
    scope.usePlugin(interactablePreventDefault);
  }
  function doOnInteractions(method, scope) {
    return function (event) {
      var interactions = scope.interactions.list;
      var pointerType = getPointerType(event);
      var _pointerUtils$getEven = getEventTargets(event),
        eventTarget = _pointerUtils$getEven[0],
        curEventTarget = _pointerUtils$getEven[1];
      var matches = []; // [ [pointer, interaction], ...]

      if (/^touch/.test(event.type)) {
        scope.prevTouchTime = scope.now();

        // @ts-expect-error
        for (var _i10 = 0, _event$changedTouches2 = event.changedTouches; _i10 < _event$changedTouches2.length; _i10++) {
          var changedTouch = _event$changedTouches2[_i10];
          var pointer = changedTouch;
          var pointerId = getPointerId(pointer);
          var searchDetails = {
            pointer: pointer,
            pointerId: pointerId,
            pointerType: pointerType,
            eventType: event.type,
            eventTarget: eventTarget,
            curEventTarget: curEventTarget,
            scope: scope
          };
          var interaction = getInteraction(searchDetails);
          matches.push([searchDetails.pointer, searchDetails.eventTarget, searchDetails.curEventTarget, interaction]);
        }
      } else {
        var invalidPointer = false;
        if (!browser$1.supportsPointerEvent && /mouse/.test(event.type)) {
          // ignore mouse events while touch interactions are active
          for (var i = 0; i < interactions.length && !invalidPointer; i++) {
            invalidPointer = interactions[i].pointerType !== 'mouse' && interactions[i].pointerIsDown;
          }

          // try to ignore mouse events that are simulated by the browser
          // after a touch event
          invalidPointer = invalidPointer || scope.now() - scope.prevTouchTime < 500 ||
          // on iOS and Firefox Mobile, MouseEvent.timeStamp is zero if simulated
          event.timeStamp === 0;
        }
        if (!invalidPointer) {
          var _searchDetails = {
            pointer: event,
            pointerId: getPointerId(event),
            pointerType: pointerType,
            eventType: event.type,
            curEventTarget: curEventTarget,
            eventTarget: eventTarget,
            scope: scope
          };
          var _interaction = getInteraction(_searchDetails);
          matches.push([_searchDetails.pointer, _searchDetails.eventTarget, _searchDetails.curEventTarget, _interaction]);
        }
      }

      // eslint-disable-next-line no-shadow
      for (var _i12 = 0; _i12 < matches.length; _i12++) {
        var _matches$_i = matches[_i12],
          _pointer = _matches$_i[0],
          _eventTarget = _matches$_i[1],
          _curEventTarget = _matches$_i[2],
          _interaction2 = _matches$_i[3];
        _interaction2[method](_pointer, event, _eventTarget, _curEventTarget);
      }
    };
  }
  function getInteraction(searchDetails) {
    var pointerType = searchDetails.pointerType,
      scope = searchDetails.scope;
    var foundInteraction = finder$1.search(searchDetails);
    var signalArg = {
      interaction: foundInteraction,
      searchDetails: searchDetails
    };
    scope.fire('interactions:find', signalArg);
    return signalArg.interaction || scope.interactions.new({
      pointerType: pointerType
    });
  }
  function onDocSignal(_ref2, eventMethodName) {
    var doc = _ref2.doc,
      scope = _ref2.scope,
      options = _ref2.options;
    var docEvents = scope.interactions.docEvents,
      events = scope.events;
    var eventMethod = events[eventMethodName];
    if (scope.browser.isIOS && !options.events) {
      options.events = {
        passive: false
      };
    }

    // delegate event listener
    for (var eventType in events.delegatedEvents) {
      eventMethod(doc, eventType, events.delegateListener);
      eventMethod(doc, eventType, events.delegateUseCapture, true);
    }
    var eventOptions = options && options.events;
    for (var _i14 = 0; _i14 < docEvents.length; _i14++) {
      var _docEvents$_i = docEvents[_i14],
        _type = _docEvents$_i.type,
        listener = _docEvents$_i.listener;
      eventMethod(doc, _type, listener, eventOptions);
    }
  }
  var interactions = {
    id: 'core/interactions',
    install: install$4,
    listeners: {
      'scope:add-document': function scopeAddDocument(arg) {
        return onDocSignal(arg, 'add');
      },
      'scope:remove-document': function scopeRemoveDocument(arg) {
        return onDocSignal(arg, 'remove');
      },
      'interactable:unset': function interactableUnset(_ref3, scope) {
        var interactable = _ref3.interactable;
        // Stop and destroy related interactions when an Interactable is unset
        for (var i = scope.interactions.list.length - 1; i >= 0; i--) {
          var interaction = scope.interactions.list[i];
          if (interaction.interactable !== interactable) {
            continue;
          }
          interaction.stop();
          scope.fire('interactions:destroy', {
            interaction: interaction
          });
          interaction.destroy();
          if (scope.interactions.list.length > 2) {
            scope.interactions.list.splice(i, 1);
          }
        }
      }
    },
    onDocSignal: onDocSignal,
    doOnInteractions: doOnInteractions,
    methodNames: methodNames
  };
  var interactions$1 = interactions;

  var OnOffMethod = /*#__PURE__*/function (OnOffMethod) {
    OnOffMethod[OnOffMethod["On"] = 0] = "On";
    OnOffMethod[OnOffMethod["Off"] = 1] = "Off";
    return OnOffMethod;
  }(OnOffMethod || {});
  /**
   * ```ts
   * const interactable = interact('.cards')
   *   .draggable({
   *     listeners: { move: event => console.log(event.type, event.pageX, event.pageY) }
   *   })
   *   .resizable({
   *     listeners: { move: event => console.log(event.rect) },
   *     modifiers: [interact.modifiers.restrictEdges({ outer: 'parent' })]
   *   })
   * ```
   */
  var Interactable = /*#__PURE__*/function () {
    function Interactable(target, options, defaultContext, scopeEvents) {
      _classCallCheck(this, Interactable);
      this.target = void 0;
      /** @internal */
      this.options = void 0;
      /** @internal */
      this._actions = void 0;
      /** @internal */
      this.events = new Eventable();
      /** @internal */
      this._context = void 0;
      /** @internal */
      this._win = void 0;
      /** @internal */
      this._doc = void 0;
      /** @internal */
      this._scopeEvents = void 0;
      this._actions = options.actions;
      this.target = target;
      this._context = options.context || defaultContext;
      this._win = getWindow(trySelector(target) ? this._context : target);
      this._doc = this._win.document;
      this._scopeEvents = scopeEvents;
      this.set(options);
    }
    _createClass(Interactable, [{
      key: "_defaults",
      get: /** @internal */function get() {
        return {
          base: {},
          perAction: {},
          actions: {}
        };
      }
    }, {
      key: "setOnEvents",
      value: function setOnEvents(actionName, phases) {
        if (is.func(phases.onstart)) {
          this.on("".concat(actionName, "start"), phases.onstart);
        }
        if (is.func(phases.onmove)) {
          this.on("".concat(actionName, "move"), phases.onmove);
        }
        if (is.func(phases.onend)) {
          this.on("".concat(actionName, "end"), phases.onend);
        }
        if (is.func(phases.oninertiastart)) {
          this.on("".concat(actionName, "inertiastart"), phases.oninertiastart);
        }
        return this;
      }
    }, {
      key: "updatePerActionListeners",
      value: function updatePerActionListeners(actionName, prev, cur) {
        var _this$_actions$map$ac,
          _this = this;
        var actionFilter = (_this$_actions$map$ac = this._actions.map[actionName]) == null ? void 0 : _this$_actions$map$ac.filterEventType;
        var filter = function filter(type) {
          return (actionFilter == null || actionFilter(type)) && isNonNativeEvent(type, _this._actions);
        };
        if (is.array(prev) || is.object(prev)) {
          this._onOff(OnOffMethod.Off, actionName, prev, undefined, filter);
        }
        if (is.array(cur) || is.object(cur)) {
          this._onOff(OnOffMethod.On, actionName, cur, undefined, filter);
        }
      }
    }, {
      key: "setPerAction",
      value: function setPerAction(actionName, options) {
        var defaults = this._defaults;

        // for all the default per-action options
        for (var optionName_ in options) {
          var optionName = optionName_;
          var actionOptions = this.options[actionName];
          var optionValue = options[optionName];

          // remove old event listeners and add new ones
          if (optionName === 'listeners') {
            this.updatePerActionListeners(actionName, actionOptions.listeners, optionValue);
          }

          // if the option value is an array
          if (is.array(optionValue)) {
            actionOptions[optionName] = from(optionValue);
          }
          // if the option value is an object
          else if (is.plainObject(optionValue)) {
            actionOptions[optionName] = extend(actionOptions[optionName] || {}, clone(optionValue));

            // set anabled field to true if it exists in the defaults
            if (is.object(defaults.perAction[optionName]) && 'enabled' in defaults.perAction[optionName]) {
              actionOptions[optionName].enabled = optionValue.enabled !== false;
            }
          }
          // if the option value is a boolean and the default is an object
          else if (is.bool(optionValue) && is.object(defaults.perAction[optionName])) {
            actionOptions[optionName].enabled = optionValue;
          }
          // if it's anything else, do a plain assignment
          else {
            actionOptions[optionName] = optionValue;
          }
        }
      }

      /**
       * The default function to get an Interactables bounding rect. Can be
       * overridden using {@link Interactable.rectChecker}.
       *
       * @param {Element} [element] The element to measure.
       * @return {Rect} The object's bounding rectangle.
       */
    }, {
      key: "getRect",
      value: function getRect(element) {
        element = element || (is.element(this.target) ? this.target : null);
        if (is.string(this.target)) {
          element = element || this._context.querySelector(this.target);
        }
        return getElementRect(element);
      }

      /**
       * Returns or sets the function used to calculate the interactable's
       * element's rectangle
       *
       * @param {function} [checker] A function which returns this Interactable's
       * bounding rectangle. See {@link Interactable.getRect}
       * @return {function | object} The checker function or this Interactable
       */
    }, {
      key: "rectChecker",
      value: function rectChecker(checker) {
        var _this2 = this;
        if (is.func(checker)) {
          this.getRect = function (element) {
            var rect = extend({}, checker.apply(_this2, element));
            if (!('width' in rect)) {
              rect.width = rect.right - rect.left;
              rect.height = rect.bottom - rect.top;
            }
            return rect;
          };
          return this;
        }
        if (checker === null) {
          delete this.getRect;
          return this;
        }
        return this.getRect;
      }

      /** @internal */
    }, {
      key: "_backCompatOption",
      value: function _backCompatOption(optionName, newValue) {
        if (trySelector(newValue) || is.object(newValue)) {
          this.options[optionName] = newValue;
          for (var action in this._actions.map) {
            this.options[action][optionName] = newValue;
          }
          return this;
        }
        return this.options[optionName];
      }

      /**
       * Gets or sets the origin of the Interactable's element.  The x and y
       * of the origin will be subtracted from action event coordinates.
       *
       * @param {Element | object | string} [origin] An HTML or SVG Element whose
       * rect will be used, an object eg. { x: 0, y: 0 } or string 'parent', 'self'
       * or any CSS selector
       *
       * @return {object} The current origin or this Interactable
       */
    }, {
      key: "origin",
      value: function origin(newValue) {
        return this._backCompatOption('origin', newValue);
      }

      /**
       * Returns or sets the mouse coordinate types used to calculate the
       * movement of the pointer.
       *
       * @param {string} [newValue] Use 'client' if you will be scrolling while
       * interacting; Use 'page' if you want autoScroll to work
       * @return {string | object} The current deltaSource or this Interactable
       */
    }, {
      key: "deltaSource",
      value: function deltaSource(newValue) {
        if (newValue === 'page' || newValue === 'client') {
          this.options.deltaSource = newValue;
          return this;
        }
        return this.options.deltaSource;
      }

      /** @internal */
    }, {
      key: "getAllElements",
      value: function getAllElements() {
        var target = this.target;
        if (is.string(target)) {
          return Array.from(this._context.querySelectorAll(target));
        }
        if (is.func(target) && target.getAllElements) {
          return target.getAllElements();
        }
        return is.element(target) ? [target] : [];
      }

      /**
       * Gets the selector context Node of the Interactable. The default is
       * `window.document`.
       *
       * @return {Node} The context Node of this Interactable
       */
    }, {
      key: "context",
      value: function context() {
        return this._context;
      }
    }, {
      key: "inContext",
      value: function inContext(element) {
        return this._context === element.ownerDocument || nodeContains(this._context, element);
      }

      /** @internal */
    }, {
      key: "testIgnoreAllow",
      value: function testIgnoreAllow(options, targetNode, eventTarget) {
        return !this.testIgnore(options.ignoreFrom, targetNode, eventTarget) && this.testAllow(options.allowFrom, targetNode, eventTarget);
      }

      /** @internal */
    }, {
      key: "testAllow",
      value: function testAllow(allowFrom, targetNode, element) {
        if (!allowFrom) {
          return true;
        }
        if (!is.element(element)) {
          return false;
        }
        if (is.string(allowFrom)) {
          return matchesUpTo(element, allowFrom, targetNode);
        } else if (is.element(allowFrom)) {
          return nodeContains(allowFrom, element);
        }
        return false;
      }

      /** @internal */
    }, {
      key: "testIgnore",
      value: function testIgnore(ignoreFrom, targetNode, element) {
        if (!ignoreFrom || !is.element(element)) {
          return false;
        }
        if (is.string(ignoreFrom)) {
          return matchesUpTo(element, ignoreFrom, targetNode);
        } else if (is.element(ignoreFrom)) {
          return nodeContains(ignoreFrom, element);
        }
        return false;
      }

      /**
       * Calls listeners for the given InteractEvent type bound globally
       * and directly to this Interactable
       *
       * @param {InteractEvent} iEvent The InteractEvent object to be fired on this
       * Interactable
       * @return {Interactable} this Interactable
       */
    }, {
      key: "fire",
      value: function fire(iEvent) {
        this.events.fire(iEvent);
        return this;
      }

      /** @internal */
    }, {
      key: "_onOff",
      value: function _onOff(method, typeArg, listenerArg, options, filter) {
        if (is.object(typeArg) && !is.array(typeArg)) {
          options = listenerArg;
          listenerArg = null;
        }
        var listeners = normalize(typeArg, listenerArg, filter);
        for (var _type in listeners) {
          if (_type === 'wheel') {
            _type = browser$1.wheelEvent;
          }
          for (var _i2 = 0, _listeners$_type2 = listeners[_type]; _i2 < _listeners$_type2.length; _i2++) {
            var listener = _listeners$_type2[_i2];
            // if it is an action event type
            if (isNonNativeEvent(_type, this._actions)) {
              this.events[method === OnOffMethod.On ? 'on' : 'off'](_type, listener);
            }
            // delegated event
            else if (is.string(this.target)) {
              this._scopeEvents[method === OnOffMethod.On ? 'addDelegate' : 'removeDelegate'](this.target, this._context, _type, listener, options);
            }
            // remove listener from this Interactable's element
            else {
              this._scopeEvents[method === OnOffMethod.On ? 'add' : 'remove'](this.target, _type, listener, options);
            }
          }
        }
        return this;
      }

      /**
       * Binds a listener for an InteractEvent, pointerEvent or DOM event.
       *
       * @param {string | array | object} types The types of events to listen
       * for
       * @param {function | array | object} [listener] The event listener function(s)
       * @param {object | boolean} [options] options object or useCapture flag for
       * addEventListener
       * @return {Interactable} This Interactable
       */
    }, {
      key: "on",
      value: function on(types, listener, options) {
        return this._onOff(OnOffMethod.On, types, listener, options);
      }

      /**
       * Removes an InteractEvent, pointerEvent or DOM event listener.
       *
       * @param {string | array | object} types The types of events that were
       * listened for
       * @param {function | array | object} [listener] The event listener function(s)
       * @param {object | boolean} [options] options object or useCapture flag for
       * removeEventListener
       * @return {Interactable} This Interactable
       */
    }, {
      key: "off",
      value: function off(types, listener, options) {
        return this._onOff(OnOffMethod.Off, types, listener, options);
      }

      /**
       * Reset the options of this Interactable
       *
       * @param {object} options The new settings to apply
       * @return {object} This Interactable
       */
    }, {
      key: "set",
      value: function set(options) {
        var defaults = this._defaults;
        if (!is.object(options)) {
          options = {};
        }
        this.options = clone(defaults.base);
        for (var actionName_ in this._actions.methodDict) {
          var actionName = actionName_;
          var methodName = this._actions.methodDict[actionName];
          this.options[actionName] = {};
          this.setPerAction(actionName, extend(extend({}, defaults.perAction), defaults.actions[actionName]));
          this[methodName](options[actionName]);
        }
        for (var setting in options) {
          if (setting === 'getRect') {
            this.rectChecker(options.getRect);
            continue;
          }
          if (is.func(this[setting])) {
            this[setting](options[setting]);
          }
        }
        return this;
      }

      /**
       * Remove this interactable from the list of interactables and remove it's
       * action capabilities and event listeners
       */
    }, {
      key: "unset",
      value: function unset() {
        if (is.string(this.target)) {
          // remove delegated events
          for (var _type2 in this._scopeEvents.delegatedEvents) {
            var delegated = this._scopeEvents.delegatedEvents[_type2];
            for (var i = delegated.length - 1; i >= 0; i--) {
              var _delegated$i = delegated[i],
                selector = _delegated$i.selector,
                context = _delegated$i.context,
                listeners = _delegated$i.listeners;
              if (selector === this.target && context === this._context) {
                delegated.splice(i, 1);
              }
              for (var l = listeners.length - 1; l >= 0; l--) {
                this._scopeEvents.removeDelegate(this.target, this._context, _type2, listeners[l][0], listeners[l][1]);
              }
            }
          }
        } else {
          this._scopeEvents.remove(this.target, 'all');
        }
      }
    }]);
    return Interactable;
  }();

  var InteractableSet = /*#__PURE__*/function () {
    function InteractableSet(scope) {
      var _this = this;
      _classCallCheck(this, InteractableSet);
      // all set interactables
      this.list = [];
      this.selectorMap = {};
      this.scope = void 0;
      this.scope = scope;
      scope.addListeners({
        'interactable:unset': function interactableUnset(_ref) {
          var interactable = _ref.interactable;
          var target = interactable.target;
          var interactablesOnTarget = is.string(target) ? _this.selectorMap[target] : target[_this.scope.id];
          var targetIndex = findIndex(interactablesOnTarget, function (i) {
            return i === interactable;
          });
          interactablesOnTarget.splice(targetIndex, 1);
        }
      });
    }
    _createClass(InteractableSet, [{
      key: "new",
      value: function _new(target, options) {
        options = extend(options || {}, {
          actions: this.scope.actions
        });
        var interactable = new this.scope.Interactable(target, options, this.scope.document, this.scope.events);
        this.scope.addDocument(interactable._doc);
        this.list.push(interactable);
        if (is.string(target)) {
          if (!this.selectorMap[target]) {
            this.selectorMap[target] = [];
          }
          this.selectorMap[target].push(interactable);
        } else {
          if (!interactable.target[this.scope.id]) {
            Object.defineProperty(target, this.scope.id, {
              value: [],
              configurable: true
            });
          }
          target[this.scope.id].push(interactable);
        }
        this.scope.fire('interactable:new', {
          target: target,
          options: options,
          interactable: interactable,
          win: this.scope._win
        });
        return interactable;
      }
    }, {
      key: "getExisting",
      value: function getExisting(target, options) {
        var context = options && options.context || this.scope.document;
        var isSelector = is.string(target);
        var interactablesOnTarget = isSelector ? this.selectorMap[target] : target[this.scope.id];
        if (!interactablesOnTarget) return undefined;
        return find(interactablesOnTarget, function (interactable) {
          return interactable._context === context && (isSelector || interactable.inContext(target));
        });
      }
    }, {
      key: "forEachMatch",
      value: function forEachMatch(node, callback) {
        for (var _i2 = 0, _this$list2 = this.list; _i2 < _this$list2.length; _i2++) {
          var _interactable = _this$list2[_i2];
          var ret = void 0;
          if ((is.string(_interactable.target) ?
          // target is a selector and the element matches
          is.element(node) && matchesSelector(node, _interactable.target) :
          // target is the element
          node === _interactable.target) &&
          // the element is in context
          _interactable.inContext(node)) {
            ret = callback(_interactable);
          }
          if (ret !== undefined) {
            return ret;
          }
        }
      }
    }]);
    return InteractableSet;
  }();

  /**
   * ```js
   * interact('#draggable').draggable(true)
   *
   * var rectables = interact('rect')
   * rectables
   *   .gesturable(true)
   *   .on('gesturemove', function (event) {
   *       // ...
   *   })
   * ```
   *
   * The methods of this variable can be used to set elements as interactables
   * and also to change various default settings.
   *
   * Calling it as a function and passing an element or a valid CSS selector
   * string returns an Interactable object which has various methods to configure
   * it.
   *
   * @param {Element | string} target The HTML or SVG Element to interact with
   * or CSS selector
   * @return {Interactable}
   */

  function createInteractStatic(scope) {
    var interact = function interact(target, options) {
      var interactable = scope.interactables.getExisting(target, options);
      if (!interactable) {
        interactable = scope.interactables.new(target, options);
        interactable.events.global = interact.globalEvents;
      }
      return interactable;
    };

    // expose the functions used to calculate multi-touch properties
    interact.getPointerAverage = pointerAverage;
    interact.getTouchBBox = touchBBox;
    interact.getTouchDistance = touchDistance;
    interact.getTouchAngle = touchAngle;
    interact.getElementRect = getElementRect;
    interact.getElementClientRect = getElementClientRect;
    interact.matchesSelector = matchesSelector;
    interact.closest = closest;
    interact.globalEvents = {};

    // eslint-disable-next-line no-undef
    interact.version = "1.10.27";
    interact.scope = scope;
    interact.use = function (plugin, options) {
      this.scope.usePlugin(plugin, options);
      return this;
    };
    interact.isSet = function (target, options) {
      return !!this.scope.interactables.get(target, options && options.context);
    };
    interact.on = warnOnce(function on(type, listener, options) {
      if (is.string(type) && type.search(' ') !== -1) {
        type = type.trim().split(/ +/);
      }
      if (is.array(type)) {
        for (var _i2 = 0, _ref2 = type; _i2 < _ref2.length; _i2++) {
          var eventType = _ref2[_i2];
          this.on(eventType, listener, options);
        }
        return this;
      }
      if (is.object(type)) {
        for (var prop in type) {
          this.on(prop, type[prop], listener);
        }
        return this;
      }

      // if it is an InteractEvent type, add listener to globalEvents
      if (isNonNativeEvent(type, this.scope.actions)) {
        // if this type of event was never bound
        if (!this.globalEvents[type]) {
          this.globalEvents[type] = [listener];
        } else {
          this.globalEvents[type].push(listener);
        }
      }
      // If non InteractEvent type, addEventListener to document
      else {
        this.scope.events.add(this.scope.document, type, listener, {
          options: options
        });
      }
      return this;
    }, 'The interact.on() method is being deprecated');
    interact.off = warnOnce(function off(type, listener, options) {
      if (is.string(type) && type.search(' ') !== -1) {
        type = type.trim().split(/ +/);
      }
      if (is.array(type)) {
        for (var _i4 = 0, _type2 = type; _i4 < _type2.length; _i4++) {
          var eventType = _type2[_i4];
          this.off(eventType, listener, options);
        }
        return this;
      }
      if (is.object(type)) {
        for (var prop in type) {
          this.off(prop, type[prop], listener);
        }
        return this;
      }
      if (isNonNativeEvent(type, this.scope.actions)) {
        var index;
        if (type in this.globalEvents && (index = this.globalEvents[type].indexOf(listener)) !== -1) {
          this.globalEvents[type].splice(index, 1);
        }
      } else {
        this.scope.events.remove(this.scope.document, type, listener, options);
      }
      return this;
    }, 'The interact.off() method is being deprecated');
    interact.debug = function () {
      return this.scope;
    };
    interact.supportsTouch = function () {
      return browser$1.supportsTouch;
    };
    interact.supportsPointerEvent = function () {
      return browser$1.supportsPointerEvent;
    };
    interact.stop = function () {
      for (var _i6 = 0, _this$scope$interacti2 = this.scope.interactions.list; _i6 < _this$scope$interacti2.length; _i6++) {
        var interaction = _this$scope$interacti2[_i6];
        interaction.stop();
      }
      return this;
    };
    interact.pointerMoveTolerance = function (newValue) {
      if (is.number(newValue)) {
        this.scope.interactions.pointerMoveTolerance = newValue;
        return this;
      }
      return this.scope.interactions.pointerMoveTolerance;
    };
    interact.addDocument = function (doc, options) {
      this.scope.addDocument(doc, options);
    };
    interact.removeDocument = function (doc) {
      this.scope.removeDocument(doc);
    };
    return interact;
  }

  /** @internal */
  var Scope = /*#__PURE__*/function () {
    function Scope() {
      var _this = this;
      _classCallCheck(this, Scope);
      this.id = "__interact_scope_".concat(Math.floor(Math.random() * 100));
      this.isInitialized = false;
      this.listenerMaps = [];
      this.browser = browser$1;
      this.defaults = clone(defaults$7);
      this.Eventable = Eventable;
      this.actions = {
        map: {},
        phases: {
          start: true,
          move: true,
          end: true
        },
        methodDict: {},
        phaselessTypes: {}
      };
      this.interactStatic = createInteractStatic(this);
      this.InteractEvent = InteractEvent;
      this.Interactable = void 0;
      this.interactables = new InteractableSet(this);
      // main window
      this._win = void 0;
      // main document
      this.document = void 0;
      // main window
      this.window = void 0;
      // all documents being listened to
      this.documents = [];
      this._plugins = {
        list: [],
        map: {}
      };
      this.onWindowUnload = function (event) {
        return _this.removeDocument(event.target);
      };
      var scope = this;
      this.Interactable = /*#__PURE__*/function (_InteractableBase) {
        _inherits(_class2, _InteractableBase);
        var _super = _createSuper(_class2);
        function _class2() {
          _classCallCheck(this, _class2);
          return _super.apply(this, arguments);
        }
        _createClass(_class2, [{
          key: "_defaults",
          get: function get() {
            return scope.defaults;
          }
        }, {
          key: "set",
          value: function set(options) {
            _get(_getPrototypeOf(_class2.prototype), "set", this).call(this, options);
            scope.fire('interactable:set', {
              options: options,
              interactable: this
            });
            return this;
          }
        }, {
          key: "unset",
          value: function unset() {
            _get(_getPrototypeOf(_class2.prototype), "unset", this).call(this);
            var index = scope.interactables.list.indexOf(this);
            if (index < 0) return;
            scope.interactables.list.splice(index, 1);
            scope.fire('interactable:unset', {
              interactable: this
            });
          }
        }]);
        return _class2;
      }(Interactable);
    }
    _createClass(Scope, [{
      key: "addListeners",
      value: function addListeners(map, id) {
        this.listenerMaps.push({
          id: id,
          map: map
        });
      }
    }, {
      key: "fire",
      value: function fire(name, arg) {
        for (var _i2 = 0, _this$listenerMaps2 = this.listenerMaps; _i2 < _this$listenerMaps2.length; _i2++) {
          var listener = _this$listenerMaps2[_i2].map[name];
          if (!!listener && listener(arg, this, name) === false) {
            return false;
          }
        }
      }
    }, {
      key: "init",
      value: function init(window) {
        return this.isInitialized ? this : initScope(this, window);
      }
    }, {
      key: "pluginIsInstalled",
      value: function pluginIsInstalled(plugin) {
        var id = plugin.id;
        return id ? !!this._plugins.map[id] : this._plugins.list.indexOf(plugin) !== -1;
      }
    }, {
      key: "usePlugin",
      value: function usePlugin(plugin, options) {
        if (!this.isInitialized) {
          return this;
        }
        if (this.pluginIsInstalled(plugin)) {
          return this;
        }
        if (plugin.id) {
          this._plugins.map[plugin.id] = plugin;
        }
        this._plugins.list.push(plugin);
        if (plugin.install) {
          plugin.install(this, options);
        }
        if (plugin.listeners && plugin.before) {
          var index = 0;
          var len = this.listenerMaps.length;
          var before = plugin.before.reduce(function (acc, id) {
            acc[id] = true;
            acc[pluginIdRoot(id)] = true;
            return acc;
          }, {});
          for (; index < len; index++) {
            var otherId = this.listenerMaps[index].id;
            if (otherId && (before[otherId] || before[pluginIdRoot(otherId)])) {
              break;
            }
          }
          this.listenerMaps.splice(index, 0, {
            id: plugin.id,
            map: plugin.listeners
          });
        } else if (plugin.listeners) {
          this.listenerMaps.push({
            id: plugin.id,
            map: plugin.listeners
          });
        }
        return this;
      }
    }, {
      key: "addDocument",
      value: function addDocument(doc, options) {
        // do nothing if document is already known
        if (this.getDocIndex(doc) !== -1) {
          return false;
        }
        var window = getWindow(doc);
        options = options ? extend({}, options) : {};
        this.documents.push({
          doc: doc,
          options: options
        });
        this.events.documents.push(doc);

        // don't add an unload event for the main document
        // so that the page may be cached in browser history
        if (doc !== this.document) {
          this.events.add(window, 'unload', this.onWindowUnload);
        }
        this.fire('scope:add-document', {
          doc: doc,
          window: window,
          scope: this,
          options: options
        });
      }
    }, {
      key: "removeDocument",
      value: function removeDocument(doc) {
        var index = this.getDocIndex(doc);
        var window = getWindow(doc);
        var options = this.documents[index].options;
        this.events.remove(window, 'unload', this.onWindowUnload);
        this.documents.splice(index, 1);
        this.events.documents.splice(index, 1);
        this.fire('scope:remove-document', {
          doc: doc,
          window: window,
          scope: this,
          options: options
        });
      }
    }, {
      key: "getDocIndex",
      value: function getDocIndex(doc) {
        for (var i = 0; i < this.documents.length; i++) {
          if (this.documents[i].doc === doc) {
            return i;
          }
        }
        return -1;
      }
    }, {
      key: "getDocOptions",
      value: function getDocOptions(doc) {
        var docIndex = this.getDocIndex(doc);
        return docIndex === -1 ? null : this.documents[docIndex].options;
      }
    }, {
      key: "now",
      value: function now() {
        return (this.window.Date || Date).now();
      }
    }]);
    return Scope;
  }();

  // Keep Scope class internal, but expose minimal interface to avoid broken types when Scope is stripped out

  /** @internal */
  function initScope(scope, window) {
    scope.isInitialized = true;
    if (is.window(window)) {
      init$3(window);
    }
    domObjects$1.init(window);
    browser$1.init(window);
    raf.init(window);

    // @ts-expect-error
    scope.window = window;
    scope.document = window.document;
    scope.usePlugin(interactions$1);
    scope.usePlugin(events);
    return scope;
  }
  function pluginIdRoot(id) {
    return id && id.replace(/\/.*$/, '');
  }

  var scope = new Scope();
  var interact = scope.interactStatic;
  var interact$1 = interact;
  var _global = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : window;
  scope.init(_global);

  var edgeTarget = (function () {});

  var elements = (function () {});

  var grid = (function (grid) {
    var coordFields = [['x', 'y'], ['left', 'top'], ['right', 'bottom'], ['width', 'height']].filter(function (_ref) {
      var xField = _ref[0],
        yField = _ref[1];
      return xField in grid || yField in grid;
    });
    var gridFunc = function gridFunc(x, y) {
      var range = grid.range,
        _grid$limits = grid.limits,
        limits = _grid$limits === void 0 ? {
          left: -Infinity,
          right: Infinity,
          top: -Infinity,
          bottom: Infinity
        } : _grid$limits,
        _grid$offset = grid.offset,
        offset = _grid$offset === void 0 ? {
          x: 0,
          y: 0
        } : _grid$offset;
      var result = {
        range: range,
        grid: grid,
        x: null,
        y: null
      };
      for (var _i2 = 0; _i2 < coordFields.length; _i2++) {
        var _coordFields$_i = coordFields[_i2],
          xField = _coordFields$_i[0],
          yField = _coordFields$_i[1];
        var gridx = Math.round((x - offset.x) / grid[xField]);
        var gridy = Math.round((y - offset.y) / grid[yField]);
        result[xField] = Math.max(limits.left, Math.min(limits.right, gridx * grid[xField] + offset.x));
        result[yField] = Math.max(limits.top, Math.min(limits.bottom, gridy * grid[yField] + offset.y));
      }
      return result;
    };
    gridFunc.grid = grid;
    gridFunc.coordFields = coordFields;
    return gridFunc;
  });

  /* eslint-disable import/no-named-as-default, import/no-unresolved */

  var allSnappers = /*#__PURE__*/Object.freeze({
    __proto__: null,
    edgeTarget: edgeTarget,
    elements: elements,
    grid: grid
  });

  var snappersPlugin = {
    id: 'snappers',
    install: function install(scope) {
      var interact = scope.interactStatic;
      interact.snappers = extend(interact.snappers || {}, allSnappers);
      interact.createSnapGrid = interact.snappers.grid;
    }
  };
  var snappers = snappersPlugin;

  var aspectRatio = {
    start: function start(arg) {
      var state = arg.state,
        rect = arg.rect,
        edges = arg.edges,
        coords = arg.pageCoords;
      var _state$options = state.options,
        ratio = _state$options.ratio,
        enabled = _state$options.enabled;
      var _state$options2 = state.options,
        equalDelta = _state$options2.equalDelta,
        modifiers = _state$options2.modifiers;
      if (ratio === 'preserve') {
        ratio = rect.width / rect.height;
      }
      state.startCoords = extend({}, coords);
      state.startRect = extend({}, rect);
      state.ratio = ratio;
      state.equalDelta = equalDelta;
      var linkedEdges = state.linkedEdges = {
        top: edges.top || edges.left && !edges.bottom,
        left: edges.left || edges.top && !edges.right,
        bottom: edges.bottom || edges.right && !edges.top,
        right: edges.right || edges.bottom && !edges.left
      };
      state.xIsPrimaryAxis = !!(edges.left || edges.right);
      if (state.equalDelta) {
        var sign = (linkedEdges.left ? 1 : -1) * (linkedEdges.top ? 1 : -1);
        state.edgeSign = {
          x: sign,
          y: sign
        };
      } else {
        state.edgeSign = {
          x: linkedEdges.left ? -1 : 1,
          y: linkedEdges.top ? -1 : 1
        };
      }
      if (enabled !== false) {
        extend(edges, linkedEdges);
      }
      if (!(modifiers != null && modifiers.length)) return;
      var subModification = new Modification(arg.interaction);
      subModification.copyFrom(arg.interaction.modification);
      subModification.prepareStates(modifiers);
      state.subModification = subModification;
      subModification.startAll(_objectSpread2({}, arg));
    },
    set: function set(arg) {
      var state = arg.state,
        rect = arg.rect,
        coords = arg.coords;
      var linkedEdges = state.linkedEdges;
      var initialCoords = extend({}, coords);
      var aspectMethod = state.equalDelta ? setEqualDelta : setRatio;
      extend(arg.edges, linkedEdges);
      aspectMethod(state, state.xIsPrimaryAxis, coords, rect);
      if (!state.subModification) {
        return null;
      }
      var correctedRect = extend({}, rect);
      addEdges(linkedEdges, correctedRect, {
        x: coords.x - initialCoords.x,
        y: coords.y - initialCoords.y
      });
      var result = state.subModification.setAll(_objectSpread2(_objectSpread2({}, arg), {}, {
        rect: correctedRect,
        edges: linkedEdges,
        pageCoords: coords,
        prevCoords: coords,
        prevRect: correctedRect
      }));
      var delta = result.delta;
      if (result.changed) {
        var xIsCriticalAxis = Math.abs(delta.x) > Math.abs(delta.y);

        // do aspect modification again with critical edge axis as primary
        aspectMethod(state, xIsCriticalAxis, result.coords, result.rect);
        extend(coords, result.coords);
      }
      return result.eventProps;
    },
    defaults: {
      ratio: 'preserve',
      equalDelta: false,
      modifiers: [],
      enabled: false
    }
  };
  function setEqualDelta(_ref, xIsPrimaryAxis, coords) {
    var startCoords = _ref.startCoords,
      edgeSign = _ref.edgeSign;
    if (xIsPrimaryAxis) {
      coords.y = startCoords.y + (coords.x - startCoords.x) * edgeSign.y;
    } else {
      coords.x = startCoords.x + (coords.y - startCoords.y) * edgeSign.x;
    }
  }
  function setRatio(_ref2, xIsPrimaryAxis, coords, rect) {
    var startRect = _ref2.startRect,
      startCoords = _ref2.startCoords,
      ratio = _ref2.ratio,
      edgeSign = _ref2.edgeSign;
    if (xIsPrimaryAxis) {
      var newHeight = rect.width / ratio;
      coords.y = startCoords.y + (newHeight - startRect.height) * edgeSign.y;
    } else {
      var newWidth = rect.height * ratio;
      coords.x = startCoords.x + (newWidth - startRect.width) * edgeSign.x;
    }
  }
  var aspectRatio$1 = makeModifier(aspectRatio, 'aspectRatio');

  var noop = function noop() {};
  noop._defaults = {};
  var rubberband = noop;

  function start$5(_ref) {
    var rect = _ref.rect,
      startOffset = _ref.startOffset,
      state = _ref.state,
      interaction = _ref.interaction,
      pageCoords = _ref.pageCoords;
    var options = state.options;
    var elementRect = options.elementRect;
    var offset = extend({
      left: 0,
      top: 0,
      right: 0,
      bottom: 0
    }, options.offset || {});
    if (rect && elementRect) {
      var restriction = getRestrictionRect(options.restriction, interaction, pageCoords);
      if (restriction) {
        var widthDiff = restriction.right - restriction.left - rect.width;
        var heightDiff = restriction.bottom - restriction.top - rect.height;
        if (widthDiff < 0) {
          offset.left += widthDiff;
          offset.right += widthDiff;
        }
        if (heightDiff < 0) {
          offset.top += heightDiff;
          offset.bottom += heightDiff;
        }
      }
      offset.left += startOffset.left - rect.width * elementRect.left;
      offset.top += startOffset.top - rect.height * elementRect.top;
      offset.right += startOffset.right - rect.width * (1 - elementRect.right);
      offset.bottom += startOffset.bottom - rect.height * (1 - elementRect.bottom);
    }
    state.offset = offset;
  }
  function set$4(_ref2) {
    var coords = _ref2.coords,
      interaction = _ref2.interaction,
      state = _ref2.state;
    var options = state.options,
      offset = state.offset;
    var restriction = getRestrictionRect(options.restriction, interaction, coords);
    if (!restriction) return;
    var rect = xywhToTlbr(restriction);
    coords.x = Math.max(Math.min(rect.right - offset.right, coords.x), rect.left + offset.left);
    coords.y = Math.max(Math.min(rect.bottom - offset.bottom, coords.y), rect.top + offset.top);
  }
  function getRestrictionRect(value, interaction, coords) {
    if (is.func(value)) {
      return resolveRectLike(value, interaction.interactable, interaction.element, [coords.x, coords.y, interaction]);
    } else {
      return resolveRectLike(value, interaction.interactable, interaction.element);
    }
  }
  var defaults$6 = {
    restriction: null,
    elementRect: null,
    offset: null,
    endOnly: false,
    enabled: false
  };
  var restrict = {
    start: start$5,
    set: set$4,
    defaults: defaults$6
  };
  var restrict$1 = makeModifier(restrict, 'restrict');

  // This modifier adds the options.resize.restrictEdges setting which sets min and
  // max for the top, left, bottom and right edges of the target being resized.
  //
  // interact(target).resize({
  //   edges: { top: true, left: true },
  //   restrictEdges: {
  //     inner: { top: 200, left: 200, right: 400, bottom: 400 },
  //     outer: { top:   0, left:   0, right: 600, bottom: 600 },
  //   },
  // })

  var noInner = {
    top: +Infinity,
    left: +Infinity,
    bottom: -Infinity,
    right: -Infinity
  };
  var noOuter = {
    top: -Infinity,
    left: -Infinity,
    bottom: +Infinity,
    right: +Infinity
  };
  function start$4(_ref) {
    var interaction = _ref.interaction,
      startOffset = _ref.startOffset,
      state = _ref.state;
    var options = state.options;
    var offset;
    if (options) {
      var offsetRect = getRestrictionRect(options.offset, interaction, interaction.coords.start.page);
      offset = rectToXY(offsetRect);
    }
    offset = offset || {
      x: 0,
      y: 0
    };
    state.offset = {
      top: offset.y + startOffset.top,
      left: offset.x + startOffset.left,
      bottom: offset.y - startOffset.bottom,
      right: offset.x - startOffset.right
    };
  }
  function set$3(_ref2) {
    var coords = _ref2.coords,
      edges = _ref2.edges,
      interaction = _ref2.interaction,
      state = _ref2.state;
    var offset = state.offset,
      options = state.options;
    if (!edges) {
      return;
    }
    var page = extend({}, coords);
    var inner = getRestrictionRect(options.inner, interaction, page) || {};
    var outer = getRestrictionRect(options.outer, interaction, page) || {};
    fixRect(inner, noInner);
    fixRect(outer, noOuter);
    if (edges.top) {
      coords.y = Math.min(Math.max(outer.top + offset.top, page.y), inner.top + offset.top);
    } else if (edges.bottom) {
      coords.y = Math.max(Math.min(outer.bottom + offset.bottom, page.y), inner.bottom + offset.bottom);
    }
    if (edges.left) {
      coords.x = Math.min(Math.max(outer.left + offset.left, page.x), inner.left + offset.left);
    } else if (edges.right) {
      coords.x = Math.max(Math.min(outer.right + offset.right, page.x), inner.right + offset.right);
    }
  }
  function fixRect(rect, defaults) {
    for (var _i2 = 0, _ref4 = ['top', 'left', 'bottom', 'right']; _i2 < _ref4.length; _i2++) {
      var edge = _ref4[_i2];
      if (!(edge in rect)) {
        rect[edge] = defaults[edge];
      }
    }
    return rect;
  }
  var defaults$5 = {
    inner: null,
    outer: null,
    offset: null,
    endOnly: false,
    enabled: false
  };
  var restrictEdges = {
    noInner: noInner,
    noOuter: noOuter,
    start: start$4,
    set: set$3,
    defaults: defaults$5
  };
  var restrictEdges$1 = makeModifier(restrictEdges, 'restrictEdges');

  var defaults$4 = extend({
    get elementRect() {
      return {
        top: 0,
        left: 0,
        bottom: 1,
        right: 1
      };
    },
    set elementRect(_) {}
  }, restrict.defaults);
  var restrictRect = {
    start: restrict.start,
    set: restrict.set,
    defaults: defaults$4
  };
  var restrictRect$1 = makeModifier(restrictRect, 'restrictRect');

  var noMin = {
    width: -Infinity,
    height: -Infinity
  };
  var noMax = {
    width: +Infinity,
    height: +Infinity
  };
  function start$3(arg) {
    return restrictEdges.start(arg);
  }
  function set$2(arg) {
    var interaction = arg.interaction,
      state = arg.state,
      rect = arg.rect,
      edges = arg.edges;
    var options = state.options;
    if (!edges) {
      return;
    }
    var minSize = tlbrToXywh(getRestrictionRect(options.min, interaction, arg.coords)) || noMin;
    var maxSize = tlbrToXywh(getRestrictionRect(options.max, interaction, arg.coords)) || noMax;
    state.options = {
      endOnly: options.endOnly,
      inner: extend({}, restrictEdges.noInner),
      outer: extend({}, restrictEdges.noOuter)
    };
    if (edges.top) {
      state.options.inner.top = rect.bottom - minSize.height;
      state.options.outer.top = rect.bottom - maxSize.height;
    } else if (edges.bottom) {
      state.options.inner.bottom = rect.top + minSize.height;
      state.options.outer.bottom = rect.top + maxSize.height;
    }
    if (edges.left) {
      state.options.inner.left = rect.right - minSize.width;
      state.options.outer.left = rect.right - maxSize.width;
    } else if (edges.right) {
      state.options.inner.right = rect.left + minSize.width;
      state.options.outer.right = rect.left + maxSize.width;
    }
    restrictEdges.set(arg);
    state.options = options;
  }
  var defaults$3 = {
    min: null,
    max: null,
    endOnly: false,
    enabled: false
  };
  var restrictSize = {
    start: start$3,
    set: set$2,
    defaults: defaults$3
  };
  var restrictSize$1 = makeModifier(restrictSize, 'restrictSize');

  function start$2(arg) {
    var interaction = arg.interaction,
      interactable = arg.interactable,
      element = arg.element,
      rect = arg.rect,
      state = arg.state,
      startOffset = arg.startOffset;
    var options = state.options;
    var origin = options.offsetWithOrigin ? getOrigin(arg) : {
      x: 0,
      y: 0
    };
    var snapOffset;
    if (options.offset === 'startCoords') {
      snapOffset = {
        x: interaction.coords.start.page.x,
        y: interaction.coords.start.page.y
      };
    } else {
      var offsetRect = resolveRectLike(options.offset, interactable, element, [interaction]);
      snapOffset = rectToXY(offsetRect) || {
        x: 0,
        y: 0
      };
      snapOffset.x += origin.x;
      snapOffset.y += origin.y;
    }
    var relativePoints = options.relativePoints;
    state.offsets = rect && relativePoints && relativePoints.length ? relativePoints.map(function (relativePoint, index) {
      return {
        index: index,
        relativePoint: relativePoint,
        x: startOffset.left - rect.width * relativePoint.x + snapOffset.x,
        y: startOffset.top - rect.height * relativePoint.y + snapOffset.y
      };
    }) : [{
      index: 0,
      relativePoint: null,
      x: snapOffset.x,
      y: snapOffset.y
    }];
  }
  function set$1(arg) {
    var interaction = arg.interaction,
      coords = arg.coords,
      state = arg.state;
    var options = state.options,
      offsets = state.offsets;
    var origin = getOriginXY(interaction.interactable, interaction.element, interaction.prepared.name);
    var page = extend({}, coords);
    var targets = [];
    if (!options.offsetWithOrigin) {
      page.x -= origin.x;
      page.y -= origin.y;
    }
    for (var _i2 = 0, _ref2 = offsets; _i2 < _ref2.length; _i2++) {
      var _offset = _ref2[_i2];
      var relativeX = page.x - _offset.x;
      var relativeY = page.y - _offset.y;
      for (var _index = 0, len = options.targets.length; _index < len; _index++) {
        var snapTarget = options.targets[_index];
        var target = void 0;
        if (is.func(snapTarget)) {
          target = snapTarget(relativeX, relativeY, interaction._proxy, _offset, _index);
        } else {
          target = snapTarget;
        }
        if (!target) {
          continue;
        }
        targets.push({
          x: (is.number(target.x) ? target.x : relativeX) + _offset.x,
          y: (is.number(target.y) ? target.y : relativeY) + _offset.y,
          range: is.number(target.range) ? target.range : options.range,
          source: snapTarget,
          index: _index,
          offset: _offset
        });
      }
    }
    var closest = {
      target: null,
      inRange: false,
      distance: 0,
      range: 0,
      delta: {
        x: 0,
        y: 0
      }
    };
    for (var _i4 = 0; _i4 < targets.length; _i4++) {
      var _target = targets[_i4];
      var range = _target.range;
      var dx = _target.x - page.x;
      var dy = _target.y - page.y;
      var distance = hypot(dx, dy);
      var inRange = distance <= range;

      // Infinite targets count as being out of range
      // compared to non infinite ones that are in range
      if (range === Infinity && closest.inRange && closest.range !== Infinity) {
        inRange = false;
      }
      if (!closest.target || (inRange ?
      // is the closest target in range?
      closest.inRange && range !== Infinity ?
      // the pointer is relatively deeper in this target
      distance / range < closest.distance / closest.range :
      // this target has Infinite range and the closest doesn't
      range === Infinity && closest.range !== Infinity ||
      // OR this target is closer that the previous closest
      distance < closest.distance :
      // The other is not in range and the pointer is closer to this target
      !closest.inRange && distance < closest.distance)) {
        closest.target = _target;
        closest.distance = distance;
        closest.range = range;
        closest.inRange = inRange;
        closest.delta.x = dx;
        closest.delta.y = dy;
      }
    }
    if (closest.inRange) {
      coords.x = closest.target.x;
      coords.y = closest.target.y;
    }
    state.closest = closest;
    return closest;
  }
  function getOrigin(arg) {
    var element = arg.interaction.element;
    var optionsOrigin = rectToXY(resolveRectLike(arg.state.options.origin, null, null, [element]));
    var origin = optionsOrigin || getOriginXY(arg.interactable, element, arg.interaction.prepared.name);
    return origin;
  }
  var defaults$2 = {
    range: Infinity,
    targets: null,
    offset: null,
    offsetWithOrigin: true,
    origin: null,
    relativePoints: null,
    endOnly: false,
    enabled: false
  };
  var snap = {
    start: start$2,
    set: set$1,
    defaults: defaults$2
  };
  var snap$1 = makeModifier(snap, 'snap');

  // This modifier allows snapping of the size of targets during resize
  // interactions.

  function start$1(arg) {
    var state = arg.state,
      edges = arg.edges;
    var options = state.options;
    if (!edges) {
      return null;
    }
    arg.state = {
      options: {
        targets: null,
        relativePoints: [{
          x: edges.left ? 0 : 1,
          y: edges.top ? 0 : 1
        }],
        offset: options.offset || 'self',
        origin: {
          x: 0,
          y: 0
        },
        range: options.range
      }
    };
    state.targetFields = state.targetFields || [['width', 'height'], ['x', 'y']];
    snap.start(arg);
    state.offsets = arg.state.offsets;
    arg.state = state;
  }
  function set(arg) {
    var interaction = arg.interaction,
      state = arg.state,
      coords = arg.coords;
    var options = state.options,
      offsets = state.offsets;
    var relative = {
      x: coords.x - offsets[0].x,
      y: coords.y - offsets[0].y
    };
    state.options = extend({}, options);
    state.options.targets = [];
    for (var _i2 = 0, _ref2 = options.targets || []; _i2 < _ref2.length; _i2++) {
      var snapTarget = _ref2[_i2];
      var target = void 0;
      if (is.func(snapTarget)) {
        target = snapTarget(relative.x, relative.y, interaction);
      } else {
        target = snapTarget;
      }
      if (!target) {
        continue;
      }
      for (var _i4 = 0, _state$targetFields2 = state.targetFields; _i4 < _state$targetFields2.length; _i4++) {
        var _state$targetFields2$ = _state$targetFields2[_i4],
          xField = _state$targetFields2$[0],
          yField = _state$targetFields2$[1];
        if (xField in target || yField in target) {
          target.x = target[xField];
          target.y = target[yField];
          break;
        }
      }
      state.options.targets.push(target);
    }
    var returnValue = snap.set(arg);
    state.options = options;
    return returnValue;
  }
  var defaults$1 = {
    range: Infinity,
    targets: null,
    offset: null,
    endOnly: false,
    enabled: false
  };
  var snapSize = {
    start: start$1,
    set: set,
    defaults: defaults$1
  };
  var snapSize$1 = makeModifier(snapSize, 'snapSize');

  /**
   * @module modifiers/snapEdges
   *
   * @description
   * This modifier allows snapping of the edges of targets during resize
   * interactions.
   *
   * ```js
   * interact(target).resizable({
   *   snapEdges: {
   *     targets: [interact.snappers.grid({ x: 100, y: 50 })],
   *   },
   * })
   *
   * interact(target).resizable({
   *   snapEdges: {
   *     targets: [
   *       interact.snappers.grid({
   *        top: 50,
   *        left: 50,
   *        bottom: 100,
   *        right: 100,
   *       }),
   *     ],
   *   },
   * })
   * ```
   */

  function start(arg) {
    var edges = arg.edges;
    if (!edges) {
      return null;
    }
    arg.state.targetFields = arg.state.targetFields || [[edges.left ? 'left' : 'right', edges.top ? 'top' : 'bottom']];
    return snapSize.start(arg);
  }
  var snapEdges = {
    start: start,
    set: snapSize.set,
    defaults: extend(clone(snapSize.defaults), {
      targets: undefined,
      range: undefined,
      offset: {
        x: 0,
        y: 0
      }
    })
  };
  var snapEdges$1 = makeModifier(snapEdges, 'snapEdges');

  /* eslint-disable n/no-extraneous-import, import/no-unresolved */
  var all = {
    aspectRatio: aspectRatio$1,
    restrictEdges: restrictEdges$1,
    restrict: restrict$1,
    restrictRect: restrictRect$1,
    restrictSize: restrictSize$1,
    snapEdges: snapEdges$1,
    snap: snap$1,
    snapSize: snapSize$1,
    spring: rubberband,
    avoid: rubberband,
    transform: rubberband,
    rubberband: rubberband
  };

  /* eslint-enable import/no-duplicates */

  var modifiers = {
    id: 'modifiers',
    install: function install(scope) {
      var interact = scope.interactStatic;
      scope.usePlugin(base);
      scope.usePlugin(snappers);
      interact.modifiers = all;

      // for backwrads compatibility
      for (var type in all) {
        var _all = all[type],
          _defaults = _all._defaults,
          _methods = _all._methods;
        _defaults._methods = _methods;
        scope.defaults.perAction[type] = _defaults;
      }
    }
  };
  var modifiers$1 = modifiers;

  var PointerEvent = /*#__PURE__*/function (_BaseEvent) {
    _inherits(PointerEvent, _BaseEvent);
    var _super = _createSuper(PointerEvent);
    function PointerEvent(type, pointer, event, eventTarget, interaction, timeStamp) {
      var _this;
      _classCallCheck(this, PointerEvent);
      _this = _super.call(this, interaction);
      pointerExtend(_assertThisInitialized(_this), event);
      if (event !== pointer) {
        pointerExtend(_assertThisInitialized(_this), pointer);
      }
      _this.timeStamp = timeStamp;
      _this.originalEvent = event;
      _this.type = type;
      _this.pointerId = getPointerId(pointer);
      _this.pointerType = getPointerType(pointer);
      _this.target = eventTarget;
      _this.currentTarget = null;
      if (type === 'tap') {
        var pointerIndex = interaction.getPointerIndex(pointer);
        _this.dt = _this.timeStamp - interaction.pointers[pointerIndex].downTime;
        var interval = _this.timeStamp - interaction.tapTime;
        _this.double = !!interaction.prevTap && interaction.prevTap.type !== 'doubletap' && interaction.prevTap.target === _this.target && interval < 500;
      } else if (type === 'doubletap') {
        _this.dt = pointer.timeStamp - interaction.tapTime;
        _this.double = true;
      }
      return _this;
    }
    _createClass(PointerEvent, [{
      key: "_subtractOrigin",
      value: function _subtractOrigin(_ref) {
        var originX = _ref.x,
          originY = _ref.y;
        this.pageX -= originX;
        this.pageY -= originY;
        this.clientX -= originX;
        this.clientY -= originY;
        return this;
      }
    }, {
      key: "_addOrigin",
      value: function _addOrigin(_ref2) {
        var originX = _ref2.x,
          originY = _ref2.y;
        this.pageX += originX;
        this.pageY += originY;
        this.clientX += originX;
        this.clientY += originY;
        return this;
      }

      /**
       * Prevent the default behaviour of the original Event
       */
    }, {
      key: "preventDefault",
      value: function preventDefault() {
        this.originalEvent.preventDefault();
      }
    }]);
    return PointerEvent;
  }(BaseEvent);

  var defaults = {
    holdDuration: 600,
    ignoreFrom: null,
    allowFrom: null,
    origin: {
      x: 0,
      y: 0
    }
  };
  var pointerEvents$1 = {
    id: 'pointer-events/base',
    before: ['inertia', 'modifiers', 'auto-start', 'actions'],
    install: install$3,
    listeners: {
      'interactions:new': addInteractionProps,
      'interactions:update-pointer': addHoldInfo,
      'interactions:move': moveAndClearHold,
      'interactions:down': function interactionsDown(arg, scope) {
        downAndStartHold(arg, scope);
        fire(arg, scope);
      },
      'interactions:up': function interactionsUp(arg, scope) {
        clearHold(arg);
        fire(arg, scope);
        tapAfterUp(arg, scope);
      },
      'interactions:cancel': function interactionsCancel(arg, scope) {
        clearHold(arg);
        fire(arg, scope);
      }
    },
    PointerEvent: PointerEvent,
    fire: fire,
    collectEventTargets: collectEventTargets,
    defaults: defaults,
    types: {
      down: true,
      move: true,
      up: true,
      cancel: true,
      tap: true,
      doubletap: true,
      hold: true
    }
  };
  function fire(arg, scope) {
    var interaction = arg.interaction,
      pointer = arg.pointer,
      event = arg.event,
      eventTarget = arg.eventTarget,
      type = arg.type,
      _arg$targets = arg.targets,
      targets = _arg$targets === void 0 ? collectEventTargets(arg, scope) : _arg$targets;
    var pointerEvent = new PointerEvent(type, pointer, event, eventTarget, interaction, scope.now());
    scope.fire('pointerEvents:new', {
      pointerEvent: pointerEvent
    });
    var signalArg = {
      interaction: interaction,
      pointer: pointer,
      event: event,
      eventTarget: eventTarget,
      targets: targets,
      type: type,
      pointerEvent: pointerEvent
    };
    for (var i = 0; i < targets.length; i++) {
      var target = targets[i];
      for (var prop in target.props || {}) {
        pointerEvent[prop] = target.props[prop];
      }
      var origin = getOriginXY(target.eventable, target.node);
      pointerEvent._subtractOrigin(origin);
      pointerEvent.eventable = target.eventable;
      pointerEvent.currentTarget = target.node;
      target.eventable.fire(pointerEvent);
      pointerEvent._addOrigin(origin);
      if (pointerEvent.immediatePropagationStopped || pointerEvent.propagationStopped && i + 1 < targets.length && targets[i + 1].node !== pointerEvent.currentTarget) {
        break;
      }
    }
    scope.fire('pointerEvents:fired', signalArg);
    if (type === 'tap') {
      // if pointerEvent should make a double tap, create and fire a doubletap
      // PointerEvent and use that as the prevTap
      var prevTap = pointerEvent.double ? fire({
        interaction: interaction,
        pointer: pointer,
        event: event,
        eventTarget: eventTarget,
        type: 'doubletap'
      }, scope) : pointerEvent;
      interaction.prevTap = prevTap;
      interaction.tapTime = prevTap.timeStamp;
    }
    return pointerEvent;
  }
  function collectEventTargets(_ref, scope) {
    var interaction = _ref.interaction,
      pointer = _ref.pointer,
      event = _ref.event,
      eventTarget = _ref.eventTarget,
      type = _ref.type;
    var pointerIndex = interaction.getPointerIndex(pointer);
    var pointerInfo = interaction.pointers[pointerIndex];

    // do not fire a tap event if the pointer was moved before being lifted
    if (type === 'tap' && (interaction.pointerWasMoved ||
    // or if the pointerup target is different to the pointerdown target
    !(pointerInfo && pointerInfo.downTarget === eventTarget))) {
      return [];
    }
    var path = getPath(eventTarget);
    var signalArg = {
      interaction: interaction,
      pointer: pointer,
      event: event,
      eventTarget: eventTarget,
      type: type,
      path: path,
      targets: [],
      node: null
    };
    for (var _i2 = 0; _i2 < path.length; _i2++) {
      var node = path[_i2];
      signalArg.node = node;
      scope.fire('pointerEvents:collect-targets', signalArg);
    }
    if (type === 'hold') {
      signalArg.targets = signalArg.targets.filter(function (target) {
        var _interaction$pointers, _interaction$pointers2;
        return target.eventable.options.holdDuration === ((_interaction$pointers = interaction.pointers[pointerIndex]) == null ? void 0 : (_interaction$pointers2 = _interaction$pointers.hold) == null ? void 0 : _interaction$pointers2.duration);
      });
    }
    return signalArg.targets;
  }
  function addInteractionProps(_ref2) {
    var interaction = _ref2.interaction;
    interaction.prevTap = null; // the most recent tap event on this interaction
    interaction.tapTime = 0; // time of the most recent tap event
  }
  function addHoldInfo(_ref3) {
    var down = _ref3.down,
      pointerInfo = _ref3.pointerInfo;
    if (!down && pointerInfo.hold) {
      return;
    }
    pointerInfo.hold = {
      duration: Infinity,
      timeout: null
    };
  }
  function clearHold(_ref4) {
    var interaction = _ref4.interaction,
      pointerIndex = _ref4.pointerIndex;
    var hold = interaction.pointers[pointerIndex].hold;
    if (hold && hold.timeout) {
      clearTimeout(hold.timeout);
      hold.timeout = null;
    }
  }
  function moveAndClearHold(arg, scope) {
    var interaction = arg.interaction,
      pointer = arg.pointer,
      event = arg.event,
      eventTarget = arg.eventTarget,
      duplicate = arg.duplicate;
    if (!duplicate && (!interaction.pointerIsDown || interaction.pointerWasMoved)) {
      if (interaction.pointerIsDown) {
        clearHold(arg);
      }
      fire({
        interaction: interaction,
        pointer: pointer,
        event: event,
        eventTarget: eventTarget,
        type: 'move'
      }, scope);
    }
  }
  function downAndStartHold(_ref5, scope) {
    var interaction = _ref5.interaction,
      pointer = _ref5.pointer,
      event = _ref5.event,
      eventTarget = _ref5.eventTarget,
      pointerIndex = _ref5.pointerIndex;
    var timer = interaction.pointers[pointerIndex].hold;
    var path = getPath(eventTarget);
    var signalArg = {
      interaction: interaction,
      pointer: pointer,
      event: event,
      eventTarget: eventTarget,
      type: 'hold',
      targets: [],
      path: path,
      node: null
    };
    for (var _i4 = 0; _i4 < path.length; _i4++) {
      var node = path[_i4];
      signalArg.node = node;
      scope.fire('pointerEvents:collect-targets', signalArg);
    }
    if (!signalArg.targets.length) return;
    var minDuration = Infinity;
    for (var _i6 = 0, _signalArg$targets2 = signalArg.targets; _i6 < _signalArg$targets2.length; _i6++) {
      var target = _signalArg$targets2[_i6];
      var holdDuration = target.eventable.options.holdDuration;
      if (holdDuration < minDuration) {
        minDuration = holdDuration;
      }
    }
    timer.duration = minDuration;
    timer.timeout = setTimeout(function () {
      fire({
        interaction: interaction,
        eventTarget: eventTarget,
        pointer: pointer,
        event: event,
        type: 'hold'
      }, scope);
    }, minDuration);
  }
  function tapAfterUp(_ref6, scope) {
    var interaction = _ref6.interaction,
      pointer = _ref6.pointer,
      event = _ref6.event,
      eventTarget = _ref6.eventTarget;
    if (!interaction.pointerWasMoved) {
      fire({
        interaction: interaction,
        eventTarget: eventTarget,
        pointer: pointer,
        event: event,
        type: 'tap'
      }, scope);
    }
  }
  function install$3(scope) {
    scope.pointerEvents = pointerEvents$1;
    scope.defaults.actions.pointerEvents = pointerEvents$1.defaults;
    extend(scope.actions.phaselessTypes, pointerEvents$1.types);
  }

  var pointerEvents$2 = /*#__PURE__*/Object.freeze({
    __proto__: null,
    default: pointerEvents$1
  });

  /* eslint-disable import/no-duplicates -- for typescript module augmentations */
  function install$2(scope) {
    scope.usePlugin(pointerEvents$1);
    var pointerEvents = scope.pointerEvents;

    // don't repeat by default
    pointerEvents.defaults.holdRepeatInterval = 0;
    pointerEvents.types.holdrepeat = scope.actions.phaselessTypes.holdrepeat = true;
  }
  function onNew(_ref) {
    var pointerEvent = _ref.pointerEvent;
    if (pointerEvent.type !== 'hold') return;
    pointerEvent.count = (pointerEvent.count || 0) + 1;
  }
  function onFired(_ref2, scope) {
    var interaction = _ref2.interaction,
      pointerEvent = _ref2.pointerEvent,
      eventTarget = _ref2.eventTarget,
      targets = _ref2.targets;
    if (pointerEvent.type !== 'hold' || !targets.length) return;

    // get the repeat interval from the first eventable
    var interval = targets[0].eventable.options.holdRepeatInterval;

    // don't repeat if the interval is 0 or less
    if (interval <= 0) return;

    // set a timeout to fire the holdrepeat event
    interaction.holdIntervalHandle = setTimeout(function () {
      scope.pointerEvents.fire({
        interaction: interaction,
        eventTarget: eventTarget,
        type: 'hold',
        pointer: pointerEvent,
        event: pointerEvent
      }, scope);
    }, interval);
  }
  function endHoldRepeat(_ref3) {
    var interaction = _ref3.interaction;
    // set the interaction's holdStopTime property
    // to stop further holdRepeat events
    if (interaction.holdIntervalHandle) {
      clearInterval(interaction.holdIntervalHandle);
      interaction.holdIntervalHandle = null;
    }
  }
  var holdRepeat = {
    id: 'pointer-events/holdRepeat',
    install: install$2,
    listeners: ['move', 'up', 'cancel', 'endall'].reduce(function (acc, enderTypes) {
      acc["pointerEvents:".concat(enderTypes)] = endHoldRepeat;
      return acc;
    }, {
      'pointerEvents:new': onNew,
      'pointerEvents:fired': onFired
    })
  };
  var holdRepeat$1 = holdRepeat;

  function install$1(scope) {
    var Interactable = scope.Interactable;
    Interactable.prototype.pointerEvents = function (options) {
      extend(this.events.options, options);
      return this;
    };
    var __backCompatOption = Interactable.prototype._backCompatOption;
    Interactable.prototype._backCompatOption = function (optionName, newValue) {
      var ret = __backCompatOption.call(this, optionName, newValue);
      if (ret === this) {
        this.events.options[optionName] = newValue;
      }
      return ret;
    };
  }
  var plugin$1 = {
    id: 'pointer-events/interactableTargets',
    install: install$1,
    listeners: {
      'pointerEvents:collect-targets': function pointerEventsCollectTargets(_ref, scope) {
        var targets = _ref.targets,
          node = _ref.node,
          type = _ref.type,
          eventTarget = _ref.eventTarget;
        scope.interactables.forEachMatch(node, function (interactable) {
          var eventable = interactable.events;
          var options = eventable.options;
          if (eventable.types[type] && eventable.types[type].length && interactable.testIgnoreAllow(options, node, eventTarget)) {
            targets.push({
              node: node,
              eventable: eventable,
              props: {
                interactable: interactable
              }
            });
          }
        });
      },
      'interactable:new': function interactableNew(_ref2) {
        var interactable = _ref2.interactable;
        interactable.events.getRect = function (element) {
          return interactable.getRect(element);
        };
      },
      'interactable:set': function interactableSet(_ref3, scope) {
        var interactable = _ref3.interactable,
          options = _ref3.options;
        extend(interactable.events.options, scope.pointerEvents.defaults);
        extend(interactable.events.options, options.pointerEvents || {});
      }
    }
  };
  var interactableTargets = plugin$1;

  /* eslint-disable import/no-duplicates -- for typescript module augmentations */
  /* eslint-enable import/no-duplicates */

  var plugin = {
    id: 'pointer-events',
    install: function install(scope) {
      scope.usePlugin(pointerEvents$2);
      scope.usePlugin(holdRepeat$1);
      scope.usePlugin(interactableTargets);
    }
  };
  var pointerEvents = plugin;

  function install(scope) {
    var Interactable = scope.Interactable;
    scope.actions.phases.reflow = true;
    Interactable.prototype.reflow = function (action) {
      return doReflow(this, action, scope);
    };
  }
  function doReflow(interactable, action, scope) {
    var elements = interactable.getAllElements();

    // tslint:disable-next-line variable-name
    var Promise = scope.window.Promise;
    var promises = Promise ? [] : null;
    var _loop = function _loop() {
      var element = elements[_i2];
      var rect = interactable.getRect(element);
      if (!rect) {
        return 1; // break
      }
      var runningInteraction = find(scope.interactions.list, function (interaction) {
        return interaction.interacting() && interaction.interactable === interactable && interaction.element === element && interaction.prepared.name === action.name;
      });
      var reflowPromise;
      if (runningInteraction) {
        runningInteraction.move();
        if (promises) {
          reflowPromise = runningInteraction._reflowPromise || new Promise(function (resolve) {
            runningInteraction._reflowResolve = resolve;
          });
        }
      } else {
        var xywh = tlbrToXywh(rect);
        var coords = {
          page: {
            x: xywh.x,
            y: xywh.y
          },
          client: {
            x: xywh.x,
            y: xywh.y
          },
          timeStamp: scope.now()
        };
        var event = coordsToEvent(coords);
        reflowPromise = startReflow(scope, interactable, element, action, event);
      }
      if (promises) {
        promises.push(reflowPromise);
      }
    };
    for (var _i2 = 0; _i2 < elements.length; _i2++) {
      if (_loop()) break;
    }
    return promises && Promise.all(promises).then(function () {
      return interactable;
    });
  }
  function startReflow(scope, interactable, element, action, event) {
    var interaction = scope.interactions.new({
      pointerType: 'reflow'
    });
    var signalArg = {
      interaction: interaction,
      event: event,
      pointer: event,
      eventTarget: element,
      phase: 'reflow'
    };
    interaction.interactable = interactable;
    interaction.element = element;
    interaction.prevEvent = event;
    interaction.updatePointer(event, event, element, true);
    setZeroCoords(interaction.coords.delta);
    copyAction(interaction.prepared, action);
    interaction._doPhase(signalArg);
    var _ref = scope.window,
      Promise = _ref.Promise;
    var reflowPromise = Promise ? new Promise(function (resolve) {
      interaction._reflowResolve = resolve;
    }) : undefined;
    interaction._reflowPromise = reflowPromise;
    interaction.start(action, interactable, element);
    if (interaction._interacting) {
      interaction.move(signalArg);
      interaction.end(event);
    } else {
      interaction.stop();
      interaction._reflowResolve();
    }
    interaction.removePointer(event, event);
    return reflowPromise;
  }
  var reflow = {
    id: 'reflow',
    install: install,
    listeners: {
      // remove completed reflow interactions
      'interactions:stop': function interactionsStop(_ref2, scope) {
        var interaction = _ref2.interaction;
        if (interaction.pointerType === 'reflow') {
          if (interaction._reflowResolve) {
            interaction._reflowResolve();
          }
          remove(scope.interactions.list, interaction);
        }
      }
    }
  };
  var reflow$1 = reflow;

  /* eslint-disable import/no-duplicates -- for typescript module augmentations */
  /* eslint-enable import/no-duplicates */

  interact$1.use(interactablePreventDefault);
  interact$1.use(offset$1);

  // pointerEvents
  interact$1.use(pointerEvents);

  // inertia
  interact$1.use(inertia$1);

  // snap, resize, etc.
  interact$1.use(modifiers$1);

  // autoStart, hold
  interact$1.use(autoStart);

  // drag and drop, resize, gesture
  interact$1.use(actions);

  // autoScroll
  interact$1.use(autoScroll$1);

  // reflow
  interact$1.use(reflow$1);

  // eslint-disable-next-line no-undef
  {
    interact$1.use(devTools);
  }
  interact$1.default = interact$1;

  if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === 'object' && !!module) {
    try {
      module.exports = interact$1;
    } catch (_unused) {}
  }
  interact$1.default = interact$1;

  return interact$1;

}));
//# sourceMappingURL=interact.js.map